Сопоставление сообщения, полученного состоянием в gen_statem в Erlang

У меня проблема с сопоставлением сообщения, полученного в татеме gen_s в модуле Erlang, который я назвал e_counter. Вот снимок кода. gen_statem связан с супервизором. Когда процесс e_counter получает сообщение о событии от другого процесса, он увеличивает счетчик. Счетчик реализован в виде записи, которая выглядит так

      -record(cntr,              {cnt       :: non_neg_integer(),
                            iv        :: non_neg_integer()}).

И определяется так

          CV = InitValues#initValues.di_CV,
    Cntr = #cntr{cnt = 0, iv = CV},

Где CV представляет значение, до которого счетчик должен считать.

Все сообщения в коде создаются с использованием записи сообщения, которая выглядит следующим образом

      -record(message,     {type                      :: event | data,
                      name                      :: atom(),
                      value                     :: any() | undefined,
                      ref                       :: reference(),  % Currently not used
                      from                      :: pid()}).

Вот снимок gen_statem

      incrCnt(cast, #message{type = event, name = ei_INCR, value = undefined, ref = _Ref, from = _From} =_Message, State) when State#state.cntr#cntr.cnt < State#state.cntr#cntr.iv ->
     io:format("Current State ~p~n", [State]),
     NewCount = State#state.cntr#cntr{cnt = State#state.cntr#cntr.cnt +1},
     io:format("Count so far ~p~n", [NewCount]),
     {next_state, incrCnt, NewCount};
incrCnt(cast, #message{type = event, name = ei_INCR, value = undefined, ref = _Ref, from = _From} = _Message, State) when State#state.cntr#cntr.cnt =:= State#state.cntr#cntr.iv ->
     NewCount = State#state.cntr#cntr{cnt =  0},
     gen_func:send_event(State#state.connections#connections.eventOut#eventOut.eo_EO),
     {next_state, incrCnt, NewCount}.

В отчете об ошибках SASL, показанном ниже, при первом получении сообщения состоянием incrCnt оно правильно сопоставляется, а в состоянии incrCnt счетчик увеличивается. Однако любые сообщения, полученные после этого, приводят к ошибке, как показано в разделе ОТЧЕТ ОБ ОШИБКАХ отчета.

      Eshell V13.1.4  (abort with ^G)
1> application:start(sasl).
ok
2> application:start(checkCntrApp).
{normal, } 
Port #Port<0.5>
ok
3> *** Different: StateBitIndxVals: [1]  ProfinetBitIndxVals *** [0]
ok ),
,ok),
Current State {state,{connections,{eventOut,{connector,ei_2,kl_2404_A}},
                                  {dataOut}},
                     {cntr,0,4}}
Count so far {cntr,1,4}
*** Different: StateBitIndxVals: [0]  ProfinetBitIndxVals *** [1]
ok ),
,ok),




=ERROR REPORT==== 28-Aug-2023::15:32:55.544317 ===
** State machine e_counter terminating
** Last event = {cast,{message,event,ei_INCR,undefined,
                               #Ref<0.4143019743.798228481.4176>,<0.104.0>}}
** When server state  = {incrCnt,{cntr,1,4}}
** Reason for termination = error:function_clause
** Callback modules = [e_counter]
** Callback mode = state_functions
** Stacktrace =
**  [{e_counter,incrCnt,
                [cast,
                 {message,event,ei_INCR,undefined,
                          #Ref<0.4143019743.798228481.4176>,<0.104.0>},
                 {cntr,1,4}],
                [{file,"src/e_counter.erl"},{line,115}]},
     {gen_statem,loop_state_callback,11,[{file,"gen_statem.erl"},{line,1426}]},
     {proc_lib,init_p_do_apply,3,[{file,"proc_lib.erl"},{line,240}]}]

Как получается, что полученное сообщение сопоставляется в первый раз и никогда после этого?

1 ответ

Возвращенный кортеж состояния{next_state, incrCnt, NewCount}переопределяет State (последнюю переменную) с помощью NewCount.
Вы напечатали NewCount, и это не структура данных State, содержащая cntr, а только cntr {cntr,1,4}.
Вторая итерация пытается получить доступ к записи состояния в Guard, но в качестве аргумента имеет NewCount, то есть запись cntr.

Другие вопросы по тегам