diff --git a/bc.lua b/bc.lua index 3d0949dd3b18..ad4c89cc4717 100644 --- a/bc.lua +++ b/bc.lua @@ -250,6 +250,31 @@ function BaseControl:call(verb, ...) error("unknown verb") end end + +function BaseControl:call_sync(verb, ...) + if self.local_verbs[verb] ~= nil then + return self.local_verbs[verb](...) + elseif self.remote_verbs[verb] ~= nil then + self.network:send(self.remote_verbs[verb], { + ty=Message.VerbRequest, + verb=verb, + param={...}, + sync=true, + }) + local answer, err = self.network:pull(function(remote, msg) + if remote ~= self.remote_nouns[noun] then return false end + if msg.ty ~= Message.NounResponse then return false end + if msg.noun ~= noun then return false end + end, timeout) + if answer ~= nil then + return table.unpack(answer.ret) + else + return nil, err + end + else + error("unknown verb") + end +end -- }}} -- Network Handler {{{ @@ -280,8 +305,17 @@ function BaseControl:_network_handler(remote, msg) -- Handled via pull elseif msg.ty == Message.VerbRequest then if self.local_verbs[msg.verb] ~= nil then - self.local_verbs[msg.verb](table.unpack(msg.param)) + local ret = table.pack(self.local_verbs[msg.verb](table.unpack(msg.param))) + if msg.sync then + self.network:send(remote, { + ty=Message.VerbResponse, + verb=msg.verb, + ret=ret, + }) + end end + elseif msg.ty == Message.VerbResponse then + -- Handled via pull else error("TODO: MessageType Unknown") end diff --git a/tests/network.lua b/tests/network.lua index c89e95f1d65c..0859cd52896c 100644 --- a/tests/network.lua +++ b/tests/network.lua @@ -75,3 +75,29 @@ function test_call_network() assert_equal(4321, tmp, "call incomplete") assert_equal(1, n, "call not correct") end + +function test_call_sync() + local bc1 = BaseControl:new() + local n = 0 + bc1:register("sync1", function(p1, p2) + assert_equal(p2, 12) + n = n + 1 + return p1 + 10, "hello" + end) + bc1:finalize() + + -- Test locally + assert_nil(bc1:call("sync1", 20, 12), "call not nil") + local ret, val = bc1:call_sync("sync1", 30, 12) + assert_equal(40, ret, "local sync not correct") + assert_equal("hello", val, "local sync not multiple") + assert_equal(2, n, "wrong invokation number") + + -- Test remote + local bc2 = BaseControl:new() + assert_nil(bc2:call("sync1", 20, 12), "call not nil") + local ret, val = bc2:call_sync("sync1", 30, 12) + assert_equal(40, ret, "local sync not correct") + assert_equal("hello", val, "local sync not multiple") + assert_equal(4, n, "wrong invokation number") +end