[erlang-questions] Fwd: Message Receive Semantics (was eep:MultiplePatterns)

Jay Nelson jay@REDACTED
Tue Jun 3 17:47:26 CEST 2008


Valentin accidentally replied directly to me:

> From: "Valentin Micic" <valentin@REDACTED>
> Date: June 2, 2008 12:02:15 AM PDT
> To: "Jay Nelson" <jay@REDACTED>
> Subject: Re: [erlang-questions] Message Receive Semantics (was  
> eep:MultiplePatterns)
>
> Hi Jay,
>
> Back in 2000, when I just started with Erlang (had a extensive  
> commercial experience in procedural languages, though), one of the  
> first problems I tried to solve had to do with priority handling.  
> So I wrote something very ugly, but someting that reflected a  
> paridgm I had at the time -- I remember writing something like this:
>
> loop_high( 0 ) -> loop_normal( 3 );
> loop_high( N ) ->
>  receive
>   {high, Msg} ->
>         process_msg( Msg ),
>         loop_high( N-1 )
>  after 0 -> receive
>        {normal, Msg}->
>             process_msg( Msg ),
>             loop_high( N )
>         after 0 -> receive
>                 { low, Msg} ->
>                        process_msg( Msg ),
>                        loop_high( N )
>                  after 0 -> receive
>                          ANY ->
>                                case process_msg( ANY ) of
>                                     stop -> exit( normal );
>                                      _      -> loop_high( N )
>                                 end
>                            after 250 -> loop_high( N )
>                   end
>         end
>  end
> end .
> loop_normal( 0 ) -> loop_low( 1 );
> loop_normal( N ) ->
>  recevie
>     {low, Msg} ->
>         process_msg( Msg ),
>         loop_normal( N-1 )
>  after 0 -> receive
>         {high, Msg} ->
>                process_msg( Msg ),
>                loop_normal( N )
>          after 0 -> ...
>                     ....
>                     ....
>           end
> end .
> loop_low( 0 ) -> loop_high( 5 );
> loop_low( N ) -> ...
> ...
> ...
>
> The above code would do the trick, however, being ugly as it may --  
> would eventually trigger refactoring to the tune of:
>
> loop_high( 0 ) -> loop_normal( 3 );
> loop_hihg(N) ->
>   receive
>      {high, Msg} ->
>          process_msg( Msg ),
>          loop_high( N-1 );
>       {normal, Msg} ->
>           process_msg( Msg ),
>           loop_high( N );
>        {low, Msg} ->
>           process_msg( Msg ),
>           loop_high(N);
>         ANY  ->
>              case process_msg( ANY ) of
>                  stop -> exit( normal );
>                  _      -> loop_high( N )
>              end
>    after 1000 -> loop_high( N )
>   end.
> loop_normal( 0 ) -> loop_low( 1 );
> loop_normal(N) ->
>   receive
>       {normal, Msg} ->
>           process_msg( Msg ),
>           loop_normal(N-1);
>      {high, Msg} ->
>          process_msg( Msg ),
>          loop_normal( N);
>      {low, Msg} ->
>           process_msg( Msg ),
>           loop_normal(N);
>         ANY  ->
>              case process_msg( ANY ) of
>                  stop -> exit( normal );
>                  _      -> loop_normal( N )
>              end
>    after 1000 -> loop_normal( N )
>   end.
> loop_low( 0 ) -> loop_high( 5 );
> loop_low(N ) -> .....
> ....
> ....
>
> What I'm trying to say, I guess -- it does not really matter if one  
> is novice or not. We all know how to think, and only through  
> thinking we can arrive to a point where we could articulate the  
> "right" kind of questions. Nothing wrong in making a few mistakes  
> in a process.
>
> BTW, how easy one may make a mistake depends largely on how the  
> problem was stated. If one says:
>
>
>
> 3) Always handle messages in the following order:
>     a) 5 messages of {reply, high, Msg}
>     b) 3 messages of {reply, normal, Msg}
>     c) 1 message of {reply, low, Msg}
>     d) 'EXIT' message
>
>
>
> one should not get surprised if the resulting code blocks until 5  
> high priority messages have been processed. However, if one  
> indicates that preference should be given to high priority  
> messages, than normal, followed by low priority message, utilising  
> a ratio of 5:3:1, and stipulate that should there be no higher  
> priority message, lower one should be processed --  one may close a  
> semantic gap, and thus prevent a novice from making a mistake. All  
> of that in far better English, of course ;-).
>
>
> V.
>
> ----- Original Message ----- From: "Jay Nelson" <jay@REDACTED>
> To: <erlang-questions@REDACTED>
> Sent: Monday, June 02, 2008 1:08 AM
> Subject: Re: [erlang-questions] Message Receive Semantics (was  
> eep:MultiplePatterns)
>
>
>> Valentin wrote:
>>
>> > Consider a following scenario: for every five "high" priority
>> messages
>> > processed, I wanted to handle three "normal" and one "low" priority
>> > message(*). To implement this with a selective receive is
>> relatively easy
>> > and concise, even for a novice programmer. To do without it, may be
>> > considerably more difficult and messy.
>>
>>
>> I think priority is one of the harder cases to get right, actually.
>> The beginner
>> will end up blocked waiting for the 5th high priority message when  
>> only
>> 4 are on the queue, or will end up delaying high priority messages  
>> while
>> they scan for low priority ones.
>>
>> So here is the concrete challenge:
>>
>> 1) Send a message to a linked process:
>>     a) {request, Msg}
>> 2) The other process should generate 20 or so messages randomly
>>     and then quit
>> 3) Always handle messages in the following order:
>>     a) 5 messages of {reply, high, Msg}
>>     b) 3 messages of {reply, normal, Msg}
>>     c) 1 message of {reply, low, Msg}
>>     d) 'EXIT' message
>>
>> Of course, there may not be 5 remaining high messages or 3 remaining
>> normal messages so you need to deal with these end cases.  In  
>> doing so,
>> make sure you don't just end up polling every 100 milliseconds.  I've
>> simplified the problem by only having one process that can generate
>> replies, so that the selective receive doesn't become even more
>> complicated.
>>
>> I challenge any beginner or intermediate erlang programmer to write
>> and post the code for both processes and  a description of your  
>> results.
>> All the advanced erlang people can help point out the issues that  
>> will
>> have to be addressed when you change the initial code approach.
>>
>> At least, that is my bet.  Valentin may be right.  Let's see some  
>> code!
>> In another post, I'll give an alternative problem that is easier and
>> shows the usefulness of selective receive.
>>
>> In general, I would argue that erlang's approach to message is geared
>> towards handling multiple conversations or sessions on a single  
>> channel,
>> and that handling priorities is a pathological case for the simple
>> message
>> queue approach that erlang uses.  It is far easier to implement
>> priorities
>> by unloading the whole queue into a process which implements a  
>> priority
>> queue and then doling out messages according to your own priority  
>> logic.
>>
>> jay
>>
>> _______________________________________________
>> erlang-questions mailing list
>> erlang-questions@REDACTED
>> http://www.erlang.org/mailman/listinfo/erlang-questions
>




More information about the erlang-questions mailing list