Big state machines

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

On 19 april 2005 16:18, Vance Shipley wrote:

> I don't know UML, and maybe never will as you've told us
> it isn't very helpful in Erlang.  :)
> In SDL an unspecified signal is implicitly handled by
> consuming it and transitioning back to the current state.
> My point was that this default behaviour is important to have.

SDL has a pretty clean representation of this, and since 
SDL has been merged into UML 2.0, the same behaviour should
be possible to specify in UML 2.0. However, I've been unable
to find it in the specification. This is not to say that 
it isn't there. In my experience, it can well take several
months to find and understand some given aspect of UML.

> I sometimes need to handle a save construct in the context of
> external signals (protocols) and gen_fsm doesn't provide the
> syntax, although erlang does.
> So the short answer I guess is that should I really need to do this
> I should implement my own system process and abandon gen_fsm.  It's
> probably a better idea than the ugliness which results from further
> bastardizing Erlang in the pursuit of retaining gen_fsm semantics.

OK, not exactly what you requested, but here's a quick hack of
gen_fsm that supports selective receive in the form of a receive
vector (gen_fsm.erl and test.erl attached).

Note: the ONLY things I've tested are the things in test.erl.


- in the init function, instead of returning {ok, NState, Data},
  one can return {selective, NState, Vector, Data [, Timeout]}
  (not tested, but "obviously works" ;-)
- As a return value from the callbacks, on can return
  {next_state_SEL, NStateName, Vector, ...} or
  {reply_SEL, Reply, NStateName, Vector, ...}
  as a complement to the old return values, which still work.

Vector is a tuple, with the following significance:

- For any event {Tag, Event}, where Tag is an integer,
  the message is consumed if element(Tag, Vector) == []
  (by convention, set element(Tag, Vector) to 'false'
- For any event {Tag, Ref, Event}, where Tag is an integer,
  the message is consumed if element(Tag, Vector) == Ref.

All other messages are left in the queue.

The unfortunate stuff with integers instead of atoms is 
of course that it's difficult to deal with atoms within
guards, if the module can't rely on record syntax (which
it can't in this case, since the records are user-provided)
We need dynamic structs!

If a timer is set with gen_fsm:start_timer/2, it can be
handled within the selective receive if the vector has 
the following form: [TimerRef, Vector], where TimerRef
is the Ref returned by gen_fsm:start_timer/2, and Vector
is a tuple as described above.

Timeouts given by the return value from the callback
are always handled.

I have no plans to support this (as perhaps evident by the
fact that I didn't rename it), but if people find it useful,
you can put pressure on OTP to consider it. ;-)

-------------- next part --------------
A non-text attachment was scrubbed...
Name: test.erl
Type: application/octet-stream
Size: 1515 bytes
Desc: test.erl
URL: <>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: gen_fsm.erl
Type: application/octet-stream
Size: 24282 bytes
Desc: gen_fsm.erl
URL: <>

More information about the erlang-questions mailing list