Anyway gen_fsm behavior is pretty weak comparing to FSM frameworks I used in C++: no on_entry / on_exit callbacks.
Also, I'm not sure you can use gen_fsm sequentially by itself (i.e. without Erlang process).
Anyway gen_fsm behavior is pretty weak comparing to FSM frameworks I used in C++: no on_entry / on_exit callbacks.
Also, I'm not sure you can use gen_fsm sequentially by itself (i.e. without Erlang process).
That's not too hard to fix; write your handle_event callback as something that observes the state, dispatches out to the "really_handle_event" function, observes the new state, and fires the desired callback, implemented however you want them to be. Ten reusable lines or so.
"Also, I'm not sure you can use gen_fsm sequentially by itself (i.e. without Erlang process)."
Not really much point, really. The gen_fsm itself is basically wrapping the state machine described there into a supervisor tree. If you don't want the supervisor tree, it is utterly trivial to write a state machine of your own in Erlang. It is one place where pattern matching excels. You want some sort of record indicating your state, then you can do things like:
-record(state, {name, val1, val2}).
event1(State=#state{name = initial}) -> handle...
event1(State=#state{name = connecting}) -> handle...
event1(State=#state{name = connected}) -> handle...
event2(State=#state{name = initial}) -> handle...
and so on. A little more plumbing is necessary to manage returning the new state but that's the basic idea, which is just about the only other thing you "get" from gen_fsm "for free".From a good FSM library I would expect following:
1. Specify human readable STT (State Transition Table)
2. For each event/state combination specify if it's valid or should be ignored, etc.
3. On entry / on exit for each state.
4. Masking/unmasking of events.
gen_fsm as it today do not provide much value over gen_server.The gen_fsm implementation is elegant and I do recommend taking a look at it but you probably won't find yourself using it all too often. At the end of the day we wanted to write a book that prepared people for real world Erlang situations and the gen_fsm does not weigh heavily in those scenarios.
riak_kv uses gen_fsm, so people looking for a real world use case could check out their usage: https://github.com/basho/riak_kv/blob/master/src/riak_kv_get... https://github.com/basho/riak_kv/blob/master/src/riak_kv_put...
I'm a relatively new to Erlang, but being familiar with gen_server made it pretty easy to understand the gen_fsm docs and figure out what was going on. I don't see the exclusion as a big deal.
For example if you have gen_server using FSM, with gen_fsm you will have 2 processes. If there was passive FSM module, you would save 1 process and handle twice as many simultaneous clients.
Some examples from boost statechart library:
http://www.boost.org/doc/libs/1_34_0/libs/statechart/doc/tut...
#include <boost/statechart/transition.hpp>
// ...
int main()
{
StopWatch myWatch;
myWatch.initiate();
myWatch.process_event( EvStartStop() );
myWatch.process_event( EvStartStop() );
myWatch.process_event( EvStartStop() );
myWatch.process_event( EvReset() );
return 0;
}FSM is abstract concept. When it's wrapped into Actor it's something else and not pure FSM. gen_fsm is more similar to Rational Rose "Capsule" design pattern, except that Capsule may have several message queues, while gen_fsm has only one. You can also mask/unmask events in Capsule.
When many years ago I first learned Erlang I thought that every process will have built-in FSM as 1st class citizen (this is what I expected from programming language designed by Telecom company).
Also what I would like from FSM module, is to be able just to specify state transition table (STT) including on entry/exit. Then the callback functions only handle state transition logic. Currently gen_fsm is very verbose for huge FSMs and I sure it's easy to introduce bugs when coding STTs.
I think the reason most people don't use gen_fsm is because it's very basic and verbose, not because there is no need in built-in FSM behaviour in OTP.
Why would you want to do that ever?