[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