[erlang-questions] EUC 2006 / proposal to enhance message receive

Jay Nelson jay@REDACTED
Thu Nov 9 16:02:23 CET 2006

Christian S wrote:
> I'm not completly convinced that out-of-band message queues is needed.
> I simply have not thought enough about the example problem you present
> for motivating it. But assuming they are very useful tools. Why do I
> just want only one priority mailbox per process?
I may have muddied the waters by using a priority example.  That was what
caused me the original issue so I've stuck with it as the problem.  I really
want a way for certain messages to not got jammed up at the back of a long
queue.  This works to separate "control" messages from "data" messages,
but could be used (or abused) for "priority" messages.

On the webpage I talk about the complexity multiple mailboxes adds to
the user's code and the likelihood of using the wrong mailbox.  It also
makes for a complicated syntax.
> Why not priority over
> priority?
> PriorityPid = oob(Pid),
> PriorityPid ! {a, message}
> HigherPriorityPid = oob(PriorityPid),
> SuperHighPriorityPid = oob(HigherPriorityPid),.... you get the idea.
Actually, I don't get the idea.  You are creating a new process for
each priority level?  I don't know what oob/1 does.  Does it launch
a new middleman process?  If so, how does the Highest priority
jump in front of lower priorities when forwarding messages?

The problem has changed a bit now.  In the original there is a single
destination that all communicating processes make a request of
(think gen_server).  Adding a priority to the message should not
cause all callers to change the way they access the service.  It
should merely be a change behind the server's facade.  So you
would add a router and worker processes as I did in the
presentation slides.
> That is, store the destination priority in the Pid object.  For
> selectively chosing priority queue in receive, introduce a new guard
> that only works there.
> receive
>   Message when priority() > 1 -> ...;
>   ...
> end

Again, I may be confused by your example, but the following does not
work at all.

Assume message queue =  [ {1, Msg}, {3, Msg}, {1, Msg}, {2, Msg} ]

loop() ->
     {P3, Msgh} when P3 == 3 -> handle_high(Msgh), loop();
     {P2, Msgm} when P2 == 2 -> handle_med(Msgm), loop();
     {P1, Msgl} when P1 == 1 -> handle_low(Msgl), loop()

The first message is matched against all clauses before continuing to
the next message.  The low priority message is processed first.  So
all the messages are processed in the order of arrival on the queue.

If you split the receive to 3 separate receive statements, you end up
with N! + N! + N scans across the queue if only low priority messages
arrive and you'll have to poll to see if there are new messages.

If you introduce a new attribute on all messages in the queue that
is a VM internal flag for priority, you get the same N! + N! + N
scanning unless you do the work on message receive to build a
structure other than a sequential list.  But putting priority requires
a client process to be able to omnisciently choose its pecking
position in the ecology of processes and process requests.

If you are proposing priority as a new concept, I think it limits the
usefulness of the feature.  I see a benefit for an arbitrary number
of channels for two communicating processes.  The channel approach
avoids the priority aproach's "client omniscience problem".
The drawbacks for multi-channel are:

1) Complexity of syntax
2) Difficulty of the resulting user models
3) Debugging requires a lot of message tracing
4) Mistakes are easy to make when juggling channel handles
5) Different syntax for existing receive code

My proposal tried to not disrupt the existing receive code or
unnecessarily complicate the implementation for the VM, yet make
a significant impact on a class of problems without intrusive syntax.
The limitation is that you only have two channels and the question is
whether that provides enough capability to be worth the effort.


More information about the erlang-questions mailing list