gen_statem

gen_statem (OTP 19+) implements finite-state machines; it replaced gen_fsm.

gen_statem (OTP 19+) implements finite-state machines; it replaced gen_fsm.

30.1 Door lock example (state_functions mode)

-module(door).
-behaviour(gen_statem).
-export([start_link/1, button/1, stop/0]).
-export([init/1, callback_mode/0, locked/3, open/3, terminate/3]).

start_link(Code) -> gen_statem:start_link({local, ?MODULE}, ?MODULE, Code, []).
button(Digit) -> gen_statem:cast(?MODULE, {button, Digit}).
stop() -> gen_statem:stop(?MODULE).

init(Code) -> {ok, locked, #{code => Code, buttons => []}}.

callback_mode() -> state_functions.

locked(cast, {button, Digit}, #{code := Code, buttons := Buttons} = Data) ->
    NewButtons = lists:sublist(Buttons ++ [Digit], length(Code)),
    case NewButtons =:= Code of
        true ->
            io:format("Unlocked!~n"),
            {next_state, open, Data#{buttons := []}, [{state_timeout, 10000, lock}]};
        false ->
            {keep_state, Data#{buttons := NewButtons}}
    end.

open(state_timeout, lock, Data) ->
    io:format("Locked again~n"),
    {next_state, locked, Data};
open(cast, {button, _}, _Data) ->
    {keep_state_and_data, [postpone]}.     % handle again after next state change

terminate(_Reason, _State, _Data) -> ok.

30.2 handle_event_function mode

State can be any term (e.g., {connected, Retries}).

callback_mode() -> [handle_event_function, state_enter].

handle_event(enter, _OldState, State, _Data) -> io:format("entering ~p~n", [State]), keep_state_and_data;
handle_event({call, From}, get_state, State, _Data) -> {keep_state_and_data, [{reply, From, State}]};
handle_event(cast, go, idle, Data) -> {next_state, running, Data};
handle_event(cast, stop, running, Data) -> {next_state, idle, Data}.

30.3 Features

Event types: {call, From}, cast, info, timeout, state_timeout, {timeout, Name}, internal, enter.

Actions: {reply, From, R}, postpone, {next_event, Type, Content} (internal events), hibernate, timeouts.

State enter calls: run code on every state entry.

Timeouts: event timeout, state timeout (cancelled on state change), generic named timeouts.