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

Frans Schneider fchschneider@REDACTED
Tue Jun 12 16:37:51 CEST 2018


Indeed, the specs are a little weird. It's for a reason the organization 
calls itself OMG.

Frans

On 06/12/2018 03:47 PM, Raimo Niskanen wrote:
> 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
>>>
> 



More information about the erlang-questions mailing list