私の作業環境はErlangです。2つの異なる機能を持つプロセスは、異なる機能に2つの受信ブロックを持つことができますか。
receive
....
end.
request()
PID!(message)
%% Can i get the reply back here instead of the receive block above?
はい、あなたは多くのreceive
表現を持つことができます。1つが評価されると、最初に一致したメッセージがメッセージキュー/メールボックスから取り出され(名前を選択して)、残りは次のメッセージに残されreceive
ます。構文(唯一の方法)を使用したメッセージの送信Pid ! Message
は完全に非同期であり、受信プロセスのメッセージキューの最後にメッセージを追加するだけです。メッセージを受信receive
する唯一の方法です。つまり、メッセージキューからメッセージを取り出します。それらを元に戻すことはできません。
Erlangに渡される組み込みの同期メッセージはありません。2つのメッセージを送信することによるものです。
「要求」プロセスは、受信プロセスにメッセージを送信してreceive
から、応答を待つためにになります。
「受信」プロセス自体がメッセージを取得してreceive
処理し、応答メッセージを「要求」プロセスに送り返し、次にreceive
座って次のメッセージを待ちます。
プロセス間には固有の接続がないことを忘れないでください。すべての通信は、非同期メッセージ送信とを使用して行われますreceive
。
したがって、2番目の質問への返信では、式でのみreceive
返信を受け取ることができます。それが唯一の方法です!
少し衒学的で申し訳ありませんが、Erlangにはブロックもステートメントもありません。これは関数型言語であり、戻り値が無視されることがある場合でも常に値を返す式しかありません。
当然のことながら、あなたはそうすることができます。
送信演算子(!)を使用してプロセスに送信されたメッセージを受信します。パターンPatternは、メールボックス内の最初のメッセージと時間順に照合され、次に2番目のメッセージと照合されます。一致が成功し、オプションのガードシーケンスGuardSeqがtrueの場合、対応するBodyが評価されます。一致するメッセージが消費され、メールボックスから削除されますが、メールボックス内の他のメッセージは変更されません。
次のコードはsupervisor2.erl
プロジェクトの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.