Erlang では、メッセージの送信者が応答を待つことができる方法はありますか? そのため、メッセージが処理された後にのみ実行を継続しますか?
そして、私は次のようなことを意味します:
Actor ! DoSomething
Continue to this next line of code when DoSomething has been processed
送信者の Pid を送信することでコールバックを行うことができることは知っていますが、他に待機する方法はありますか?
最初に理解しておくべきことは、Erlang は非同期メッセージ パッシングを処理するように構築されているということです。そのため、同期メッセージの受け渡しを行う唯一の方法は、確認応答に似たものを実装することです。
P1 と P2 の 2 つのプロセスを想像してください。P1 は次のコードを実行する可能性があります。
%% process P1 takes the Pid of P2 as a parameter
%% and a Message to pass on to P2
p1(P2, Message) ->
P2 ! {self(), Message},
receive
{P2, ok}
after 5000 -> % this section is optional, times out after 5s
exit("P2 didn't process this!") % this kills P1
end.
P2は、その側で次を実行するだけかもしれません:
p2() ->
receive
{From, Message} ->
io:format("P2 received message ~p~n",[Message]),
%% processing is done!
From ! {self(), ok}
end.
そのため、p2 を新しいプロセスとして生成することができます。これは、メッセージを待って座っています。次に p1 を呼び出すと、P2 にメッセージが送信され、P2 はそれを処理して ( io:format/2
)、P1 に応答します。P1 は応答を待っていたため、そのプロセス内で追加のコードは実行されませんでした。
これがブロッキング呼び出しを実装する基本的かつ唯一の方法です。使用する提案はgen_server:call
、私が今示したものを大まかに実装しています。ただし、プログラマーには隠されています。
受信ブロックを使用できます。
http://www.erlang.org/doc/reference_manual/expressions.html#id2270724
ドキュメントから読む:
受信は決して失敗しません。パターンの 1 つに一致し、真のガード シーケンスを持つメッセージが到着するまで、実行はおそらく無期限に中断されます。
つまり、メッセージを送信して返信を待ちます。
受信プロセスがgen_serverの場合は、 を使用できますgen_server:call
。例えば:
gen_server:call(Pid, Message),
% At this point, we know that the other process has answered.
いいえ、非同期メッセージパッシングのみがあります。
少し哲学的になりたい場合は、メッセージがいつ処理されたかを自動的に定義することは非常に困難です。メッセージがプロセスに到着したとき、受信されたがまだ処理されていないとき、または受信プロセスによって処理されたときです。これは、誰かが私のメールを「読んだ」ときに自動通知を受け取ることに似ています。はい、彼らはそれを見ましたが、彼らは本当にそれを読みましたか?
状況によって異なります。Web ブラウザーが webmachine に対して実行時間の長い erlang リソースを要求した場合、その要求を満たすためにキャストを使用する方法はありません。