问题
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 ?
回答1:
what happens in the first program is:
- you spawn the receiver at the "receive high-priority message" state
- he finds no high-priority message so he goes to "receive low-priority message" state
- you send a high priority message but it's not recognised
- you send a low priority message and it is recognised
- 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]).
来源:https://stackoverflow.com/questions/12248111/how-to-give-different-priorities-to-erlang-messages