[erlang-questions] gen_fsm + handle_info = spaghetti code?

Peer Stritzinger peerst@REDACTED
Tue Aug 6 17:02:31 CEST 2013


Whenever gen_server or gen_fsm gets in my way and the code gets 
unnecessarily convoluted just to deal with their respective way of 
doing it I just don't use them.

Instead I just write plain erlang servers with fsm's coded as one 
function per state calling each other as state transitions.  In the 
functions I just use receive statements to handle my messages.

Adiitional benefits is that I get the additional power of selective 
receive on my messages that keep my state
count and transitions lower.  This works especially well when talking 
to real world hardware or for implementing protocol layers.

For more info on why selective receive is an extra power:

http://www.infoq.com/presentations/Death-by-Accidental-Complexity

When you start your process with proc_lib:spawn_link instead of the 
normal spawn_link BIF the process can be run in a supervisor.

If you also handle system messages you get a full OTP compliant process 
(aka Special Processes).  System messages can be handled manually or 
better by using sys:handle_system_msg

Example in the slides here:

https://www.erlang-factory.com/conference/ErlangUserConference2013/speakers/LoicHoguin 


Also there would be https://github.com/uwiger/plain_fsm to help you 
write a Special Process.

One additional trick: I use gen:call to get all the nice client 
features of gen_{server,fsm}, unfortunately it isn't documented except 
here 
https://github.com/erlang/otp/blob/maint/lib/stdlib/src/gen.erl#L134 
(worth a read anyway as learning experience).

If you find yourself repeating certain patterns repeatedly: write your 
own behaviours to factor out the common things.

Cheers,
-- Peer


On 2013-08-05 16:05:56 +0000, Janos Hary said:

> All,
>  
> I’m working on an optical archiving application. I wrote a NIF wrapper 
> around a burning SDK. Other relevant parts are a task queue, which 
> holds burning or reading tasks, and a web based gui which shows the 
> drives’ state to the user. In the middle sits an Erlang module 
> controlling a physical drive, and of cause the application should 
> handle multiple drives.
> Because the drives’ state diagram is fairly complex (reading, burning, 
> handling different media capacities and types, hw events, errors, user 
> interactions on GUI or pressing the eject button, etc.) I started to 
> implement it as a gen_fsm.
> Now, my problem: most of the events triggering a state change are 
> coming in plain Erlang messages (from the NIF, or from gproc what I use 
> to connect to the GUI module). I can capture these events with 
> handle_info but I lose the major advantage of the gen_fsm. If two 
> subsequent events are coming through handle_info, I vainly specify the 
> new state, because the state’s callback won’t be ever reached. My code 
> is a bunch of handle_infos and they are just handling the specific 
> events in any state.
> What is an advisabel practice to code such an FSM?
>  
> Thanks for any ideas in advance.
> Janos






More information about the erlang-questions mailing list