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

Fred Hebert mononcqc@REDACTED
Wed Jun 13 03:03:43 CEST 2018


On 06/12, Frans Schneider wrote:
>
>__|_____________|_____________________________|____________________
>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.
>

Have you considered:

handle_event(..., ..., t2, Data) ->
    ...
    {next_state, may_send_ack, NewData,
     [{next_event, internal, switch_states}]};
handle_event(internal, switch_states, maybe_send_ack, Data) ->
    case Data of
        #data{missing_changes=[]} ->
            {next_state, waiting, Data};
        _ ->
            {next_state, must_send_ack, Data}
    end;
...


Using next_event to force-enqueue the next event lets you do a switch 
through a state transition based entirely on its internal state. It does 
require any transition to 'may_send_ack' to set that value, though.




More information about the erlang-questions mailing list