[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