Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to give different priorities to erlang messages

Tags:

erlang

In the book "erlang programming" and in this stack overflow question I have seen that we can give different priorities to erlang messages in the mailbox using:

I tried to implement something similar with this code:

-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}.

But the result was:

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

Which seems not right, so I changed the code as:

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.

and the result is the following (all high priority messages are printed before the low priority ones).

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

Is this the correct way in order to achieve my goal? And can different priorities be achieved within gen_server handle_info/2 ?

like image 897
user601836 Avatar asked Sep 03 '12 12:09

user601836


1 Answers

what happens in the first program is:

  1. you spawn the receiver at the "receive high-priority message" state
  2. he finds no high-priority message so he goes to "receive low-priority message" state
  3. you send a high priority message but it's not recognised
  4. you send a low priority message and it is recognised
  5. then the receiver loops and goes to the "high priority message" state and recognises the messages

so there could even be a deadlock where the receiver would have a ton of high-priority messages but cannot process them cause he's stuck in the low-priority state

therefore, I think that your approach (which is similar to the answer to the question you linked) is better. an optimisation: since you receive a high-priority message there is no need to send it again (and cause additional overhead):

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]).
like image 144
Thanos Tintinidis Avatar answered Oct 06 '22 23:10

Thanos Tintinidis