5

「erlangプログラミング」という本とこのスタックオーバーフローの質問では、以下を使用してメールボックス内のerlangメッセージにさまざまな優先順位を付けることができることを確認しました。

私はこのコードで似たようなものを実装しようとしました:

-module(mytest).
-export([start/0, test/0]).

start() ->
    register(?MODULE, spawn(fun() -> do_receive() end)).

do_receive() ->
    receive
        {high_p, Message} ->
            io:format("High priority: ~p~n", [Message]),
            do_receive()
    after 0 ->
            receive
                {low_p, Message} ->
                    io:format("Low priority: ~p~n", [Message]),
                    do_receive()
            end
    end.

test() ->
    mytest ! {high_p, msg1},
    mytest ! {low_p, msg2},
    mytest ! {high_p, msg3}.

しかし、結果は次のとおりです。

1> mytest:start().
true
2> mytest:test(). 
Low priority: msg2
{high_p,msg3}
High priority: msg1
High priority: msg3

これは正しくないように思われるので、コードを次のように変更しました。

do_receive() ->
    receive
        {high_p, Message} ->
            io:format("High priority: ~p~n", [Message]),
            do_receive()
    after 0 ->
            receive
                {high_p, _} = Other ->
                    self() ! Other,
                    do_receive();
                {low_p, Message} ->
                    io:format("Low priority: ~p~n", [Message]),
                    do_receive()
            end
    end.

結果は次のようになります(優先度の高いメッセージはすべて、優先度の低いメッセージの前に出力されます)。

1> mytest:start().
true
2> mytest:test(). 
High priority: msg3
{high_p,msg3}
High priority: msg1
Low priority: msg2

これは私の目標を達成するための正しい方法ですか?そして、gen_server handle_info / 2内で異なる優先順位を達成できますか?

4

1 に答える 1

9

最初のプログラムで何が起こるかは次のとおりです。

  1. 「優先度の高いメッセージを受信する」状態でレシーバーを生成します
  2. 優先度の高いメッセージが見つからないため、「優先度の低いメッセージを受信する」状態になります。
  3. 優先度の高いメッセージを送信しましたが、認識されません
  4. 優先度の低いメッセージを送信すると、それが認識されます
  5. 次に、受信者はループして「優先度の高いメッセージ」状態になり、メッセージを認識します

そのため、受信者が大量の優先度の高いメッセージを受信して​​も、それらを処理できないというデッドロックが発生する可能性もあります。これにより、受信者は優先度の低い状態でスタックします。

したがって、あなたのアプローチ(リンクした質問への回答に似ています)の方が優れていると思います。最適化:優先度の高いメッセージを受信するため、再度送信する必要はありません(追加のオーバーヘッドが発生します)。

do_receive() ->
    receive
        {high_p, Message} ->
            do_high(Message)
    after 0 ->
            receive
                {high_p, Message} ->
                    do_high(Message);
                {low_p, Message} ->
                    io:format("Low priority: ~p~n", [Message])
            end
    end,
    do_receive().

do_high(Message) ->
    io:format("High priority: ~p~n", [Message]).
于 2012-09-03T14:33:12.963 に答える