2012-12-01 34 views
0

我的工作环境是Erlang。 具有2个不同功能的进程可以在不同的功能中有两个接收块。一个进程是否可以有两个接收块

receive 
.... 
end. 

request() 
PID!(message) 
%% Can i get the reply back here instead of the receive block above? 

回答

11

是的,你可以有很多receive表达式。当评估一个人时,它会从消息队列/邮箱中取出第一个匹配的消息(选择名称),并将剩下的部分留给下一个receive。使用Pid ! Message语法(唯一的方法)发送消息是完全异步的,只是将消息添加到接收过程消息队列的末尾。 receive收到消息的唯一方式,即将它们从消息队列中取出。你永远不能放回他们。

有没有内置的传递二郎同步消息时,它是一个通过发送两个消息:

  • 的“请求”的过程将消息发送到接收过程,然后进入一个receive到等待答复。

  • “接收”过程本身会收到消息receive,对其进行处理,将回复消息发送回“请求”进程,然后进入receive坐等待下一条消息。

请记住,进程之间没有固有的连接,所有通信都是使用异步消息发送和receive完成的。

所以在回答你的第二个问题:你可以只有得到一个回复​​receive表达式。这是唯一的方法!

对不起,有点迂腐,但Erlang没有块或声明。它是一种功能语言,只有表达式即使返回值有时被忽略,也总是返回一个值。

+0

非常好的解释....谢谢哥们! – Amitku

2

你可以。

接收使用发送操作符(!)发送到进程的消息。 模式Pattern依次与邮箱中的第一条消息 时间顺序匹配,然后第二条,依此类推。如果匹配 成功并且可选的保护序列GuardSeq为真,则对相应的主体进行评估。匹配邮件消耗, 从邮箱中删除,而 邮箱中的任何其他邮件保持不变。

下面的代码是从​​rabbitmq项目。它甚至使用嵌套的receive声明。下面我标记嵌套receive

terminate_simple_children(Child, Dynamics, SupName) -> 
    Pids = dict:fold(fun (Pid, _Args, Pids) -> 
         erlang:monitor(process, Pid), 
         unlink(Pid), 
         exit(Pid, child_exit_reason(Child)), 
         [Pid | Pids] 
        end, [], Dynamics), 
    TimeoutMsg = {timeout, make_ref()}, 
    TRef = timeout_start(Child, TimeoutMsg), 
    {Replies, Timedout} = 
     lists:foldl(
      fun (_Pid, {Replies, Timedout}) -> 
        {Reply, Timedout1} = 
         receive %% attention here 
          TimeoutMsg -> 
           Remaining = Pids -- [P || {P, _} <- Replies], 
           [exit(P, kill) || P <- Remaining], 
           receive {'DOWN', _MRef, process, Pid, Reason} -> %%attention here 
             {{error, Reason}, true} 
           end; 
          {'DOWN', _MRef, process, Pid, Reason} -> 
           {child_res(Child, Reason, Timedout), Timedout}; 
          {'EXIT', Pid, Reason} -> 
           receive {'DOWN', _MRef, process, Pid, _} -> 
             {{error, Reason}, Timedout} 
           end 
         end, 
        {[{Pid, Reply} | Replies], Timedout1} 
      end, {[], false}, Pids), 
    timeout_stop(Child, TRef, TimeoutMsg, Timedout), 
    ReportError = shutdown_error_reporter(SupName), 
    [case Reply of 
     {_Pid, ok}   -> ok; 
     {Pid, {error, R}} -> ReportError(R, Child#child{pid = Pid}) 
    end || Reply <- Replies], 
    ok. 
相关问题