Gen StateM

The gen_statem behaviour is based on the Mealy State Machine. In versions before OTP 20, another behaviour called Gen FSM implemented a Moore State Machine. The Mealy machine implementation improved performance for all OTP libraries.

This behavior is built on the server behavior (gen_server) (…), also adding state management at the behavior level. The difference between the server and the state machine is that an event received by a server is handled in only one dimension, the implemented code and the only existing state data. In the state machine, the code that handles each request, and each event, depends on the internal state of the state machine.

(Rubio 2022, chap. .5)

Concepts

Event Handlers

  handle_event(Type, Content, State, Data) ->
     {next_state, NextState, NewData, Actions}
   | {stop, Reason, NewData}.
   | {keep_state, ...}
   | {keep_state_and_data, ...}
   | {repeat_state, ...}
   | {stop_and_reply, ...}

  where

    Type :: cast | {call, From} | info | timeout | ...

  and you take Actions to mean "a list of Action" with
  the following signanture:

    Action ::
      % enter_action()
      %% reply_action()
      {reply, From :: from(), Reply :: term()}

      %% timeout_action()
    | {Time :: event_timeout()}
    | {timeout, Time :: event_timeout(), EventContent :: event_content()}
    | {timeout, Time :: event_timeout(), EventContent :: event_content(), Options :: timeout_options() }
    | (...)

      %% Others kinds of enter_action()
    | hibernate
    | {hibernate, Hibernate :: hibernate()}

      % Other kinds of Actions
    | postpone
    | {postpone, Postpone :: postpone()}
    | {next_event, EventType :: event_type(), EventContent :: event_content() }
    | {change_callback_module, NewModule :: module(), EventContent :: event_content() }
    | {push_callback_module, NewModule :: module()} 
    | pop_callback_module
    | ...

Event Types

  • External
-type external_event_type() :: {call, From :: from()} | cast | info.
Module Callback
gen_statem:cast(Server, Msg) Mod:StateName(cast, Msg, Data)
gen_statem:call(Server, Req) Mod:StateName({call, From}, Req, Data)
Server ! Msg Mod:StateName(info, Msg, Data)
  • Timeout
-type timeout_event_type() :: timeout | {timeout, Name :: term()} | state_timeout.
Message Callback
{timeout, Time, Msg} Mod:StateName(timeout, Msg, Data)
{{timeout, Name}, Msg, Data} Mod:StateName({timeout, Name}, Msg, Data)
{state_timeout, Msg, Data} Mod:StateName(state_timeout, Msg, Data)
  • Internal

internal events can only be generated by the state machine itself through the transition action next_event.

Message Callback
{next_event, internal, Msg} Mod:StateName(internal, Msg, Data)

References:

Rubio, Manuel. 2022. “Erlang/Otp: The Otp Basics” 2.

Backlinks: