Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Erlang: priority receive

Priority receive in Erlang can easily be implemented as follows:

prio() -> 
  receive 
    {priority, X} -> X 
  after 0 -> 
    receive 
      X -> X 
    end 
  end.

I am reading a paper called Priority Messaging made Easy, by Nyström, in which they describe the following problem:

The main problem with the [code] example [above], is that we do not take into consideration that when evaluation is resumed from the inner blocking receive we may have more than one message in the mailbox. In a worst case scenario, all but the first, of potentially a huge number, of elements could be priority messages. In this scenario we would actually have accomplished the very opposite of what we intended to do.

I don't completely get this.

Question (1): I assume that the inner blocking receive will be 'called' (i.e. resumed) as soon as one message has arrived in the message queue, right? Is it realistic to assume that in the short time it takes to resume from the inner blocking receive, there would already be a whole bunch of messages waiting in the queue?

Question (2): Also, the worst case scenario is described as a queue with one normal message and a lot of priority messages. Since all the receive clauses are first checked against the first message in the queue, and then against the second message in the queue, ...(source: this book, page 69-70) shouldn't this be: a lot of normal messages with at the end of the queue a priority message?

like image 385
Rabarberski Avatar asked Jun 06 '09 16:06

Rabarberski


3 Answers

Erlang being a radically concurrent language, there's no reason you couldn't have been sent several messages at the exact same time. Making assumptions along the lines of "Oh, this is fast -- it's so unlikely other threads would do something that conflicts in that little time" is essentially the same thing as closing your eyes and saying "There's no such thing as race conditions, there's no such thing as race conditions..."

like image 91
Chuck Avatar answered Nov 10 '22 09:11

Chuck


On (1): Whether this assumption can be made depends on details of your situation. For example, all other processes may have been waiting for something to happen before sending you their messages.

On (2): In fact, it seems to me that the worst case would be no priority messages, as the mailbox would have to be traversed every time: "Has a priority message come in yet?"

like image 5
Alexey Romanov Avatar answered Nov 10 '22 09:11

Alexey Romanov


According to the erlang reference manual receive traverses the mailbox in time order. and blocks till a message matches the one of the clauses.

Given that it sounds like the inner recieve is going to block till it recieves a matching message. Because of this you might actually stack up priority messages while waiting for non-priority messages which is the opposite of what you want.

Too ways out of this predicament are throwing a new after clause on the inner receive. Or always match in the inner recieve.

Although looking at their function the inner clause should always match but I'm guessing this is what they were talking about.

like image 2
Jeremy Wall Avatar answered Nov 10 '22 08:11

Jeremy Wall