erlang混合同步和异步功能

时间:2013-11-15 14:55:22

标签: asynchronous erlang otp

是否可以阻止同步函数(handle_call)等待另一个模块中的异步调用(handle_cast)?

即。 如何才能使同步函数等待(即阻塞),直到收到来自异步函数的特定“完成”消息? (然后才继续执行) 这两个模块都遵循gen_server和gen_fsm行为。

可以以某种方式使用handle_info吗?

此致 /彼得

1 个答案:

答案 0 :(得分:5)

执行此操作的方法是在handle_call中保存对发件人的引用,稍后再调用gen_server:reply。也就是说,虽然您通常会像这样编写handle_call函数:

handle_call(foo, _From, State) ->
    {reply, {ok, bar}, State}.
你会做这样的事情:

handle_call(foo, From, State = #state{pending = Pending}) ->
    NewState = State#state{pending = [From | Pending]},
    {noreply, NewState}.

然后,也许在handle_info

handle_info({bar_event, Data}, State = #state{pending = [Head | Tail]) ->
    gen_server:reply(Head, {ok, Data}),
    NewState = State#state{pending = Tail},
    {noreply, NewState}.

这意味着当进程调用gen_server:call(Pid, foo)时,它将一直阻塞,直到服务器进程收到{bar_event, Data},此时服务器将把事件中包含的数据返回给调用者。

我试图通过将关于调用者的信息存储在“堆栈”中来保持示例简单,因此在多个并发调用者的情况下,最后一个调用者将首先返回,反之亦然。在许多情况下,您需要使用某种键来保存调用者信息,以便在获得异步事件时可以查找。

这也可以在gen_fsm过程中完成;函数调用和返回值类似。