4

gen_server:cast/2 を使用したErlang非同期メッセージ処理の良い例を探しています。

Module:handle_cast/2 を介してリクエストを受信し、それをモジュールのローカル キューに保持し、明示的にメッセージを送信することで、後でリクエストに対応する応答メッセージを送り返す OTP ssh モジュールの例を見てきました。呼び出し元に。読んでみると、コードがほとんど理解できず、アイデアが掴めませんでした。

疑似コードの一部を歓迎します。

4

2 に答える 2

5

ssh_connection_managerモジュールを参照していると思います。

を実行するgen_server:cast/2と、リクエストはModule:handle_cast/2関数で処理されます。ここで注意すべき点がいくつかあります。

  • パラメータにはhandle_cast送信者に関する情報がないため、メッセージ自体の中でこの情報を送信しない限り、結果を送信者に返送することはできません。
  • クライアントは、を発行した後gen_server:cast/2、応答を待ちません。実際には、メッセージが到着したかどうかは関係ありません(一部の例外を除く)。
  • では、noreplyまたはstophandle_cast/2 tupleを返すことができるため、そこに応答を返す方法はありません。

そうは言っても、あなたが見ているコードの背後にある考え方は(物事を単純化する)べきです:

  • 初期同期 gen_server:call/2が行われます
  • クライアントのFromはサーバーに渡され、その状態に保存されます(実際には、その引数を使用して追加のプロセスが作成されているようです)。このトリックは、handle_callの時点で戻り値を計算できない場合に役立ちます。
  • この時点で、他のクライアント(A)または同じクライアント(B)からの結果を計算するためにさらに情報が必要かどうかに応じて、2つの可能性があります。

    • A.handle_callで{noreplyNewState}のようなものを返します。これにより、クライアントがまだ保持している間に他のリクエストを処理できるようになります。結果の準備ができたら、gen_server:reply()を使用して結果をクライアントに送り返すことができます。
    • B. {reply、ok、State}をクライアントに返します。クライアントは実行を継続し、おそらく一連のキャスト/2を実行します。次に、クライアントは新しいで最終結果を尋ねますgen_server:call/2
于 2011-06-14T23:56:36.703 に答える
4

通常、キャストを送信するときに直接の返信を期待することはありません。それ以外の場合は、gen_server:call を使用します。

実際の例として、いくつかの「チャネル」を処理する gen_server があり、エラー ログにチャネル名を追加するために多くの用途があります。チャネル名は、gen_server の状態に格納されます。エラーをログに記録したいプロセスを妨げないようにするために、「名前を取得」同期呼び出しを使用して先頭に追加する名前を取得するのではなく、キャストを使用してメッセージを送信します。

error(Pid, Tags) ->
    gen_server:cast(Pid, {log, error_report, Tags}).

warning(Pid, Tags) ->
    gen_server:cast(Pid, {log, warning_report, Tags}).

info(Pid, Tags) ->
    gen_server:cast(Pid, {log, info_report, Tags}).

キャストは非常に単純なハンドラーで処理され、返されません。

handle_cast({log, Report, Tags}, #state{name=Name}=State) ->
    error_logger:Report([{chan, Name} | Tags]),
    {noreply, State};

返送する非同期メッセージがある場合、これはキャストの処理とは完全に無関係です。どういうわけか保存しなければならないこれらのメッセージの送信先を知る必要があるかState、固定名を使用しています。

通常、メッセージを送信するだけでなく、受信プロセス モジュールの関数を呼び出す必要があります (別のキャストまたは単純なメッセージ送信である可能性があります)。

于 2011-06-14T06:52:30.407 に答える