plain_fsm - for beginners and purists

Ulf Wiger ulf.wiger@REDACTED
Wed Feb 11 17:51:21 CET 2004

On Wed, 11 Feb 2004 00:11:10 -0500, Shawn Pearce <spearce@REDACTED> 

> I have to say, I think plain_fsm is a nice advance over gen_fsm, and
> would love to see some form of it in OTP proper.

Thank you. (:

> I only have two comments:
> The parse transform wrapper doesn't make sense when you intially read
> it.  In fact, it looks like it couldn't possibly do what it is actually
> doing, as it seems like a non tail-recursive function being setup,
> which is horrible in a persistant server (yes, I know its actually
> making correct code, I'm saying that reading it initially has you
> reading it wrong):
> 	idle(S) ->
> 		plain_fsm:exented_receive(
> 			receive
> 			do_nothing -> idle(S)
> 			end).

I know. This is a problem. I thought that it was a reasonable
violation, but I agree that if you don't know that the code
is transformed into something else, it is confusing.

> I'd suggest a different parse transform, or just a plain macro:
> 	idle(S) ->
> 		receive
> 		'SYSTEM' -> 'SYSTEM';
> 		do_nothing -> idle(S)
> 		end.

This construct suffers from the same problem as my wrapper
function. The code above would terminate if it received the
message 'SYSTEM' (unless you know that there is a transformation,
of course.)

> 	idle(S) ->
> 		receive
> 		do_nothing -> idle(S)
> 		end.

I've been down this path a couple of times, but a problem that's
difficult to get around is that the ?PLAIN_FSM_SYSTEM macro needs
to pass the state (the variable S in the above example), and there
is just no elegant way to do that, I think.

> I find the second the lazyman's way out, while the first with the parse
> transform is much more elegant, and keeps to basic Erlang syntax.

My conclusion is that there is no way to do this while preserving
both syntax and semantics - assuming you want to actually simplify
things compared to what's already there in OTP.

Joe recently suggested a -compile({token_transform, Module}) directive,
so that he could use "!!" without forcing everyone to hack the parser.
Using a token transform, I could introduce a new keyword (local to the
behaviour) that would signal the change in semantics:

    idle(S) ->

(One could also imagine a directive to replace the parser...,
and why not the linter too, while we're at it. ;)

> It also lets you order the system/parent exit events with regards to the
> other events in the receive statement.

I'd have to think about whether or not that's a good thing. (:

> My other comment has to do with exit failure.  If a plain_fsm crashes
> its parent will receive the {'EXIT', P, R} message (or crash itself).
> But who writes out the error_report through error_logger?  I find this
> very valuable that every gen_server and gen_fsm process will write
> its crash report to the error log, without the developer needing to
> ensure this happens.

You change the spawn function of your FSM to one of :
  - plain_fsm:spawn(Mod, Fun)
  - plain_fsm:spawn_link(Mod, Fun)
  - plain_fsm:spawn_opt(Mod, Fun)

These will perform some local magic and then call the corresponding
functions in proc_lib.erl. Thus, you will get crash reports if the
process dies.

(BTW, the plain_fsm docs failed to mention that you need to include
"plain_fsm.hrl" in order to get the parse_transform to happen.)

Ulf Wiger, Senior System Architect

This communication is confidential and intended solely for the addressee(s). Any unauthorized review, use, disclosure or distribution is prohibited. If you believe this message has been sent to you in error, please notify the sender by replying to this transmission and delete the message without disclosing it. Thank you.

E-mail including attachments is susceptible to data corruption, interruption, unauthorized amendment, tampering and viruses, and we only send and receive e-mails on the basis that we are not liable for any such corruption, interception, amendment, tampering or viruses or any consequences thereof.

More information about the erlang-questions mailing list