Почему методы состояния gen_fsm должны что-то возвращать? - PullRequest
2 голосов
/ 29 октября 2019

Я сейчас читаю LYAE и пытаюсь понять, почему gen_fsm методы состояния должны вообще что-либо возвращать в соответствии с источником

{reply, Reply, NextStateName, NewStateData}
{reply, Reply, NextStateName, NewStateData, Timeout}
{reply, Reply, NextStateName, NewStateData, hibernate}

{next_state, NextStateName, NewStateData}
{next_state, NextStateName, NewStateData, Timeout}
{next_state, NextStateName, NewStateData, hibernate}

{stop, Reason, Reply, NewStateData}
{stop, Reason, NewStateData}

Может кто-тообъясните мне, если у меня есть 3 метода состояния: a, b и c, и конечный автомат будет определен следующим образом:

a()->
  receive
    something -> b();
    _ -> error(err)
  end.

b()->
  receive 
    somethingelse-> c();
    _ ->
  end.

Зачем мне нужен возвращаемый результатметод следующего состояния?

someMethod()->
   receive 
      _ -> 
           {next_state, NextStateName, NewStateData}=someNextMethod(),
          //why would i place code here? What could i possibly do with the above tuple ?
   end.

Я не понимаю, зачем мне ставить код ПОСЛЕ вызова метода следующего состояния? Все вызовы являются рекурсивными, поэтому кроме начального состояния, когда я мог бы что-то сделать после того, как fsm закончился или бросил, зачем мне помещать код в другие состояния?

Ответы [ 2 ]

3 голосов
/ 30 октября 2019

Вы правы, возвращаемое значение не требуется, и вы должны иметь рекурсивный вызов какой-либо функции, которая будет ожидать оператора получения: необходимо заставить вещи развиваться (из-за неизменности переменной) и реагироватьк новому сообщению.

Дело в том, что ваш пример - это конечный автомат с одним модулем, в то время как при использовании поведения gen_fsm в игре находятся как минимум 2 модуля:

  • Сам неявный и универсальный модуль поведения gen_fsm
  • и конкретный модуль обратного вызова, который вы пишете.

Каждый модуль имеет очень разные роли.

  • универсальный отвечает за сохранение состояния и получение сообщений (поэтому вы не должны заботиться об этом в своем коде), он предлагает различные виды сообщений: синхронные или асинхронные, в одно состояние или любое состояние, через интерфейс gen_fsm или"свободно отправленные" сообщения ... Он также управляет режимами работы: init, stop, изменение кода ... Он также управляет в фоновом режимевзаимодействие с системой OTP. Так как это универсальный модуль, он не может знать о состояниях и переходах, которые вы хотите определить.
  • Модуль обратного вызова вызывается gen_fsm (почти) каждый раз, когда получает сообщение. Вызываемая функция зависит от состояния и сообщения. Модуль обратного вызова отвечает за определение состояний и переходов, которые вы хотите для конечного автомата, он выполняется с помощью возвращаемого значения, возвращаемого gen_fsm. Возвращаемое значение содержит несколько полей, следующее состояние является обязательным, поскольку gen_fsm должен знать, в какое состояние «идти» - переход в состояние - это изображение, это просто имя состояния, хранящееся в переменной и поддерживаемое основным циклом fsm. - он также может хранить больше информации (обычно также называемой информацией о состоянии, которая вводит в заблуждение, например, для системы дверных замков текущий секретный код). Возвращаемое значение может также содержать другие вещи, такие как ответ вызывающей стороне в случае синхронного сообщения, тайм-аут перед следующим входящим сообщением, запрос на остановку fsm ...

Короче говоря, gen_fsmпростой рекурсивный цикл, ожидающий сообщения «событие», которые содержат, по крайней мере, переменную State_name. Он использует вспомогательные функции, хранящиеся в модуле обратного вызова, для описания своего поведения. Не так далеко от того, что вы говорите, но с ограничениями, введенными универсальным модулем, а также с преимуществами интегрированного в OTP и хорошо проверенного кода.

2 голосов
/ 30 октября 2019
   {next_state, NextStateName, NewStateData}=someNextMethod(),
   //why would i place code here? What could i possibly do with the above tuple ?

Например:

  {next_state, NextStateName, NewStateData}=someNextMethod(),
  {next_state, NextStateName, NewStateData + 1}

Или:

  {next_state, NextStateName, NewStateData}=someNextMethod(),
  ModifiedStateData = do_calculation(NewStateData),
  {next_state, NextStateName, ModifiedStateData}
...