[erlang-questions] Best practices in gen_fsm usage

Vance Shipley vances@REDACTED
Wed Dec 7 09:00:17 CET 2011

On Wed, Dec 07, 2011 at 01:31:42PM +0700, Maxim Treskin wrote:
}  1. gen_fsm incompatible with gen_server. We cannot use synchronous call
}  from gen_server for gen_fsm because it different.

Are you suggesting that you should be able to write:

     Reply = Module:call(Ref, Request)

Where Ref is a reference to either a gen_server a or gen_fsm?
You still need to use the correct module.  I don't see how much
that helps you over:

     Reply = case Module of
          gen_server ->
               gen_server:call(Ref, Request);
          gen_fsm ->
               gen_fsm:sync_send_event(Ref, Request)

}  2. Two different actions: send_event и send_all_state_event with different
}  handlers. Why? If we want to send message to FSM, we just send message to
}  process without knowledge of its internal state-related issues, right?

When you call gen_fsm:send_event/2 to send an event the function
StateName/2 in your callback module will be called for any state.
You don't need to use send_all_state_event/2 at all.  If you do
it is processed in your callback module's handle_event/3 function
and not the individual state's event handler StateName/2.

}  3. For complex protocols and when one message emits almost equal actions in
}  various process states, code of gen_fsm-process becomes pumpkinized. Every
}  time I start writing a new gen_fsm module, I think that this time the code
}  will not become pumpkinized, but this wrong. Large number of pattern
}  matching with records in events and internal state of process in various
}  state handlers makes code duplicated and unreadable.

How can it be any other way?  You say "_almost_ equal actions in 
_various_ process states".  So it's not all states and not the same 
action.  Therefore you need to uniquely handle events in states.

}  Is there any best practices in gen_fsm usage? May be I and other people
}  uses gen_fsm improperly?

Obviously putting common processing in seperate functions and calling
them from the state handlers is the way to handle 3.

If you still have a problem with 1 or 2 you might want to just simply
send messages ('Ref ! Request') and handle them in 
gen_server:handle_info/2 and gen_fsm:handle_info/3.

If you are still unsatisfied you could implement your own FSM
behaviour in place of gen_fsm.  You may find this thread interesting:



More information about the erlang-questions mailing list