views:

69

answers:

1

I noticed that messages sent to the pid of a gen_fsm process are matched in the state callbacks as events. Is this just accidental or can I rely on this feature?

Normally I would expect general messages sent to a gen_fsm to show up in the handle_info/3 callback and thought I would have to re-send it using gen_fsm:send_event.

Does gen_fsm try to match the message first to the state callback and then allways with the handle_info/3 callback? Or only if it doesn't match a state callback clause?

However when I try it my message seems to be handled twice according to debug output.

So basically the question can also be stated like: how to correctly handle received messages as events in gen_fsm state functions?


Clarification: that some of the events are occurring by getting messages passed should be considered given for this question.

I'm aware that in many cases its cleaner to make the protocol visible by using function calls into the fsm only.

I'm not so sure if this would improve the current framework where the mentioned gen_fsm has to fit in: Diverse protocol stacks where each layer calls a connect() function to attach (and sometimes start) the lower layer. Packets are sent to lower layers ba calling a function (send) and received by receiveing a message. Much like gen_tcp.

By looking at the code for gen_fsm I already figured out that general messages are only passed to handle_info, so only the question remains wether to call the state function directly from the handle_info/3 callback or resent using gen_fsm:send_event.

+1  A: 

General messages are handled by handle_info callback, unless you have something like this in your code:

handle_info(Info, StateName, StateData) -> ?MODULE:StateName(Info, StateData).

Which avoids resending, but I do not recommend neither that, nor resending.

Delivering events exclusively by means of API calls encapsulating send_event/sync_send_event/send_all_state_event/sync_send_all_state_event makes protocol explicit. Which is a right thing, as it is easier to understand, maintain and document with edoc.

probsolver
The gen_fsm for now has to fit in a given architecture of protocol stacks, that are built along the pattern: lower levels are connect()ed by higher levels packets are sent() but are received by message sending to upper levels. Similar how gen_tcp handles connections. So either I change the whole pile of code to pass callbacks instead of messages for upstream, which I rather not currently or I have to handle these messages.
Peer Stritzinger
Call directly - it's faster. Besides, in case of resending if API is used along with message passing you have no "sequential delivery from one source" guarantee.
probsolver
Thanks! I already implemented it as direct function call and it fits in nicely with the rest of the code. And it works like a breeze also.
Peer Stritzinger