[erlang-questions] gen_statem state enter call and changing t oanother state

Raimo Niskanen raimo+erlang-questions@REDACTED
Tue Jun 12 15:47:58 CEST 2018


On Tue, Jun 12, 2018 at 02:14:45PM +0200, Frans Schneider wrote:
> 
> 
> On 06/12/2018 12:31 PM, Ingela Andin wrote:
> > Hi!
> > 
> > Could it be so that you are trying to solve the problem in the wrong 
> > place? State enter actions are good for example starting a timer, but I 
> > think it is illogical to change the state.
> > It sound to me like you could do so pattern matching, maybe in 
> > conjunction with some guards in the your state function clauses and if 
> > your conditions are meet maybe
> > all that clause does is to change state.
> > 
> > Regards Ingela Erlang/OTP team - Ericsson AB
> > 
> > 
> 
> Of course I can, but in this particular case it would lead to simpler 
> code. For example, I have the following state changes defined ([1] par. 
> 8.4.12.2):
> 
>  __|_____________|_____________________________|____________________
>  T2|waiting      |HEARTBEAT message is received|if (HB.FinalFlag ==
>    |             |                             |    NOT_SET) then
>    |             |                             |  must_send_ack else if
>    |             |                             |   (HB.LivelinessFlag ==
>    |             |                             |   NOT_SET) then
>    |             |                             |  may_send_ack
>    |             |                             |else
>    |             |                             |  waiting
>  __|_____________|_____________________________|____________________
>  T3|may_send_ack |GuardCondition:              |waiting
>    |             |   WP::missing_changes() ==  |
>    |             |       <empty>               |
>  __|_____________|_____________________________|____________________
>  T4|may_send_ack |GuardCondition:              |must_send_ack
>    |             |   WP::missing_changes() !=  |
>    |             |       <empty>               |
>  __|_____________|_____________________________|____________________
>  T5|must_send_ack|after(R::heartbeatResponseDelay) waiting
>  __|_____________|_____________________________|____________________
> 
> Transitions T3/T4 are just begging for a enter state with next_state. 
> The alternative would be to put the guard conditions at the end of T2, 
> which of course is not that bad but it messes up the line of thinking of 
> the original protocol designers and its readers. Also, T3/T4 could just 
> become something like:
> 
> handle_event(enter,
> 	     _Old_state,
> 	     #state{state2 = may_send_ack} = State,
> 	     #data{missing_changes = []} = Data) ->
>      {next_state, waiting, Data};
> handle_event(enter,
> 	     _Old_state,
> 	     #state{state2 = may_send_ack} = State,
> 	     Data) ->
>      ...
>      {next_state, must_send_ack, Data};
> 
> which I think is very accurate. In the example, there is only T2 as the 
> old state but there are other examples with more than one originating 
> states.
> 
> Frans
> 
> [1] https://www.omg.org/spec/DDSI-RTPS/2.2/PDF

Your example illustrates the problem.

But I think the specification in question is very strange, and an ill fit
for an event driven state machine.

I can see that "HEARTBEAT message is received" is an event, but think it is
very strange that [WP::missing_changes() == <empty>] is an event - it seems
more like a condition on the state, and hence the state may_send_ack appears
to not be a state but instead some kind of decision point.

So the state chart "8.24 - Behavior of the Reliable StatefulReader with
respect to each matched Writer" seems to be a mix of a state diagram and a
flowchart.

Also, specifying a state machine as a table of transitions is a bit odd, but
gets even more peculiar when the events are e.g "RTPS Reader is configured with
a matched RTPS Writer." or "GuardCondition: WP::missing_changes() == <empty>"
- here again a mix between a state transition table and flowchart conditions.

Since the specification in question seems to be quite far from an event driven
state machine it is no wonder if it seems to fit gen_statem poorly... :-(

Implementing flowchart logic via pseudo state changes calling back and
forth between the behaviour engine and the callback module is strange and
inefficient, but in this case has the advantage of making the
implementation kind of match the specification.

So the question boils down to; would allowing state change from state enter
calls be bad for what gen_statem is intended to be good at?

/ Raimo



> 
> > 
> > 2018-06-12 10:31 GMT+02:00 Frans Schneider <fchschneider@REDACTED 
> > <mailto:fchschneider@REDACTED>>:
> > 
> > 
> > 
> >     On 06/12/2018 10:06 AM, Raimo Niskanen wrote:
> > 
> > 
> >         I agree.  State enter calls were introduced to allow code to be
> >         run when a
> >         state is entered, without having to duplicate that code at every
> >         state exit
> >         from the previous state.  It is a feature existing in other
> >         state machine
> >         description languages e.g OpenBSD's ifstated.
> > 
> >     This is the exact reason for bringing up the whole issue. And
> >     sometimes, that requires a next_state NewState.
> > 
> > 
> > 
> >     Frans
> > 

-- 

/ Raimo Niskanen, Erlang/OTP, Ericsson AB



More information about the erlang-questions mailing list