[erlang-questions] Best practices in gen_fsm usage

Maxim Treskin zerthurd@REDACTED
Wed Dec 7 09:13:59 CET 2011


On 7 December 2011 15:00, Vance Shipley <vances@REDACTED> wrote:

> 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)
>     end
>
> So I need to pass behaviour with pid() of process to client.


> }  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.
>
> Putting state name in #state{name = StateName} of gen_server gives
necessary result. We can do

handle_call(#request{... large pattern matching ...} = Request, From,
#state{name = StateName, ... another pattern matching...} = State) ->
  do_smth...,
  case StateName of
    %% State specific code
    ....
  end,
  do_yet_another_smth...,
  {reply, Result, State}

instead of copies `large pattern matching` Request with State if we use
gen_fsm.


> }  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:
>
>        http://erlang.org/pipermail/erlang-questions/2005-April/015097.html
>
> --
>        -Vance
>
>


-- 
Maxim Treskin
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20111207/53a85e25/attachment.htm>


More information about the erlang-questions mailing list