Big state machines

Ulf Wiger (AL/EAB) ulf.wiger@REDACTED
Tue Apr 19 13:48:44 CEST 2005

> -----Original Message-----
> From: Vance Shipley [mailto:vances@REDACTED]
> Sent: den 19 april 2005 17:52
> To: Ulf Wiger (AL/EAB)
> Cc: erlang-questions@REDACTED
> Subject: Re: Big state machines
> On Mon, Apr 18, 2005 at 10:03:59PM +0200, Ulf Wiger (AL/EAB) wrote:
> }  
> }  It's not a behaviour, but I believe that gen_fsm could
> }  perhaps be extended to hold a "receive vector" that 
> }  modifies the normal FIFO semantics.
> Maybe it could.  To get the functionality I'm looking for it would
> need to allow you to specify a list of events to receive and a list 
> of events to save.  Each of which could include an "any" construct
> (although obviously not both).

See a hacked gen_fsm that I just posted.
The list of events to save, in that case would be all events not 
specified in the vector. All events are saved if not actively 
received while in the selective mode, but this is determined
by the callback's return value. If no filter vector is given
by the return value, the normal gen_fsm semantics apply.

The idea behind this was that for "top-level" states, FIFO
semantics is perfectly fine. Thus, you provide a filter vector
for the few states that will otherwise ruin your entire state
machine design.

> I initially rejected this idea because it carries the danger that 
> you will not keep the state handler function clauses in sync with
> the "receive vector".  This may not be that big a problem though.

In the test program I wrote, I explicitly handled tuples and 
integers to identify messages. One would much prefer to use
a record. In my POTS example, I used the following record
and macro definitions:

-record(recv, {lim = [],         % replies, digit, onhook, offhook,...
               anal = [],        % analysis_reply
               half_call = []    % request_connection, connect

-define(lim, #recv.lim).
-define(anal, #recv.anal).
-define(hc, #recv.half_call).

Macros to tag messages being sent. The record to use as a receive
vector (e.g. #recv{lim = Ref, _ = false}, meaning "handle a message 
tagged as ?lim where the second element is Ref -- buffer everything

It isn't stunningly beautiful, but I've failed sofar to come
up with anything better.


More information about the erlang-questions mailing list