2017-05-23 10 views
1

に私はLearnYouSomeErlangを読んでいると、以下のコードが見つかりました:アーラン:Ref` `の使用は、クエリと応答

私の質問は、なぜ私たちはevent機能でRefが必要なのかということですが。 理由は、Refはrequest-idと似ていると思います。

複数のリクエストをdont_give_crapに送信し、返信が返された場合は、RefがどのIDであるかを教えてくれます。

しかし、eventがブロックされていて、1つのリクエストを送信しているため、同じプロセスから複数のリクエストをdont_give_crap processに送信できますか? Refの目的は何ですか?

-module(cat_fsm). 
-export([start/0, event/2]). 

start() -> 
    spawn(fun() -> dont_give_crap() end). 

event(Pid, Event) -> 
    Ref = make_ref(), % won't care for monitors here 
    Pid ! {self(), Ref, Event}, 
    receive 
    {Ref, Msg} -> {ok, Msg} 
    after 5000 -> 
     {error, timeout} 
    end. 

dont_give_crap() -> 
    receive 
    {Pid, Ref, _Msg} -> Pid ! {Ref, meh}; 
    _ -> ok 
    end, 
    io:format("Switching to 'dont_give_crap' state~n"), 
    dont_give_crap(). 

答えて

7

私の質問は、なぜ我々は文献

が必要なのですかそれは検証コードのようなものだということです。あなたのプロセスのPidがあれば、他のプロセスはあなたのプロセスにメッセージを送ることができます。

私はRefがrequest-idのような理由があると思います。

Refは返信IDとよく似ています。これは、プロセスが返信で受け取ることを期待しているIDです。

receive 
    Msg -> %%do something 
end 

この場合、プロセスのメールボックスに送信されたメッセージはそのパターンと一致し、送信元がわからないことがあります。あなたが書いている場合:

receive 
    {Pid, Msg} -> %%do something 
end 

あなたはまだメッセージがプロセスPidから来たと確信することはできません。あなたのプロセスのもう1つに、返信している複数のPidがあり、間違ってPidをメッセージに使用している可能性があります。

しかし、あなたのリクエストでRefを送信してPidを処理すると、プロセスPidは受信したRefとそのPidを含むメッセージで返信できます。その後、Refと送信者のPidを含むメッセージを抽出できますそれはプロセスPidから来ていることを確かめてください(実際にはPidはRefを他のプロセスに送ることができるので、あなたはまだ絶対に確信することはできません)。

もし100のメッセージをお互いに送信しているプロセスが1,000個あるerlangアプリケーションを持っていたなら、Pidによって返信がどこから来たのかを確かめるだけでエラーが起こりやすくなるかもしれません。

編集:私はgen_udpとソケットについて読んでいましたが、一部のサーバーでは返信を複製できます。それが起こると仮定し、クライアントは、このようなメールボックスから最初の応答を抽出:

receive 
    {Pid, Msg1} -> Msg1 
end 

クライアントは、応答のために第2の要求を待つを送信:

receive 
    {Pid, Msg2} -> Msg2 
end 

よく、そのパターンを抽出します第2の要求に対する応答ではなく、第1の要求に対する重複した応答。しかし、独自の参考と第一及び第二の要求の両方で送信されている場合:

Pid = ..., 
Ref1 = ..., 
Pid ! {self(), Ref1, Msg1}, 
receive 
    {Pid, Ref1, Reply1} -> Reply1 
end, 

Ref2 = ..., 
Pid ! {self(), Ref2, Msg2}, 
receive 
    {Pid, Ref2, Reply2} -> Reply2 
end. 

2番目は、最初のリクエストに重複回答が一致しませんでし受けます。これはRefの良い使用の具体例です。

1
  1. クエリでRefの使用と応答

各プロセスには、自宅で郵便ポストのように、自分のメールボックスを持っています。メールボックスは、任意の要求を任意のプロセスに送信するためのエントリポイントです。

コードごとに、特定のプロセスからの応答を戻したいとします。したがって、 メールボックスからのメッセージ抽出の代わりに、予想されるプロセスpidを指定する必要があります。

  1. 同じプロセスから複数のリクエストをdont_give_crapプロセスに送信できますか? Refの目的は何ですか?

これはできません。プロセスAからプロセスBへの複数の要求を送信する。A→B、すなわち、AがブロックメッセージをBに送信する場合、Aはブロック内にあり、他のプロセスからの他のメッセージを受け入れないことを意味する。

各メッセージは、メッセージ構造のパターン一致によって異なります