Structs (was RE: Record selectors)

Ulf Wiger etxuwig@REDACTED
Fri Jan 17 23:50:01 CET 2003


On Fri, 17 Jan 2003, Sean Hinde wrote:

>Well, the comments to their version of the POTS program
>from the Erlang book suggest that they see the erlang
>ability to "selectively receive" to be merely a way of
>avoiding deadlock, and they avoid such nastiness by
>statically ensuring that all objects are capable of
>receiving all valid messages at all times.

I would say that this is a big misunderstanding.

Selective receive is not at all about that, and forcing all
objects to have to deal with all messages as they come in
drastically complicates your state machine programming.

Erlang's selective receive -- being able to pattern-match on
the entire message queue -- is perhaps not absolutely
necessary (even though it is sometimes extremely valuable),
but what you need to have for complex state machine
programming is (a) the ability to stop and wait for a
specific message, and (b) the ability to single out one or a
few senders, buffering any other messages until later.
(This might also be achieved by having separate channels.)
Without this, you end up having to invent quasi states in
your code and introducing timing dependencies that will
cause nightmares in testing.

Let's take the POTS example to illustrate

getting_first_digit() ->
    receive
        {lim, onhook} ->
            lim:stop_tone(),
            idle();
        {lim, {digit, Digit}} ->
            lim:stop_tone(),
            getting_number(Digit,
                           number:analyse(
                              Digit,
                              number:valid_sequences()));
            ...
    end.

getting_number(Number, {incomplete, ValidSeqs}) ->
    receive
        {lim, onhook} ->
            idle();
        {lim, {digit, Digit}} ->
            getting_number(10 * Number + Digit,
                           number:analyse(
                              Digit,
                              ValidSeqs));
        ...
   end.

The function lim:stop_tone() actually involves sending a
message to the hardware and waiting for a reply (selective
receive). If we don't have that ability, we need to handle a
stop_tone_reply message in our state machine. Now, what if
the next digit comes in before stop_tone_reply? We must now
introduce a state (receiving a digit while waiting for
stop_tone_reply), and we must process the digit (in most
other states, we may happily ignore a pressed digit.)

In the specification of the state machine, this is not
necessary. It's a product of our programming model. And it's
a timing-dependent state, so we will have difficulty
provoking it on a real system. We can easily see that there
is absolutely no dependency in real life between the
response from our hardware and the pressing of a button on
the caller's phone. The dependency exists only in our
implementation.

If we introduce distribution, timing dependencies change,
and our code may start breaking because of untested
timing-dependent states in our code. The original Erlang
state machine is resistant to such problems because it
handles events in a logically sound order.

_That's_ why selective receive is necessary.

/Uffe
-- 
Ulf Wiger, Senior Specialist,
   / / /   Architecture & Design of Carrier-Class Software
  / / /    Strategic Product & System Management
 / / /     Ericsson Telecom AB, ATM Multiservice Networks




More information about the erlang-questions mailing list