Provided by: erlang-manpages_22.2.7+dfsg-1_all bug

NAME

       gen_fsm - Deprecated and replaced by gen_statem

DESCRIPTION

       Deprecated and replaced by gen_statem

MIGRATION TO GEN_STATEM

       Here  follows  a  simple example of turning a gen_fsm into a gen_statem. The example comes
       from the previous Users Guide for gen_fsm

       -module(code_lock).
       -define(NAME, code_lock).
       %-define(BEFORE_REWRITE, true).

       -ifdef(BEFORE_REWRITE).
       -behaviour(gen_fsm).
       -else.
       -behaviour(gen_statem).
       -endif.

       -export([start_link/1, button/1, stop/0]).

       -ifdef(BEFORE_REWRITE).
       -export([init/1, locked/2, open/2, handle_sync_event/4, handle_event/3,
             handle_info/3, terminate/3, code_change/4]).
       -else.
       -export([init/1, callback_mode/0, locked/3, open/3, terminate/3, code_change/4]).
       %% Add callback__mode/0
       %% Change arity of the state functions
       %% Remove handle_info/3
       -endif.

       -ifdef(BEFORE_REWRITE).
       start_link(Code) ->
           gen_fsm:start_link({local, ?NAME}, ?MODULE, Code, []).
       -else.
       start_link(Code) ->
           gen_statem:start_link({local,?NAME}, ?MODULE, Code, []).
       -endif.

       -ifdef(BEFORE_REWRITE).
       button(Digit) ->
           gen_fsm:send_event(?NAME, {button, Digit}).
       -else.
       button(Digit) ->
           gen_statem:cast(?NAME, {button,Digit}).
           %% send_event is asynchronous and becomes a cast
       -endif.

       -ifdef(BEFORE_REWRITE).
       stop() ->
           gen_fsm:sync_send_all_state_event(?NAME, stop).
       -else.
       stop() ->
           gen_statem:call(?NAME, stop).
           %% sync_send is synchronous and becomes call
           %% all_state is handled by callback code in gen_statem
       -endif.

       init(Code) ->
           do_lock(),
           Data = #{code => Code, remaining => Code},
           {ok, locked, Data}.

       -ifdef(BEFORE_REWRITE).
       -else.
       callback_mode() ->
           state_functions.
       %% state_functions mode is the mode most similar to
       %% gen_fsm. There is also handle_event mode which is
       %% a fairly different concept.
       -endif.

       -ifdef(BEFORE_REWRITE).
       locked({button, Digit}, Data0) ->
           case analyze_lock(Digit, Data0) of
            {open = StateName, Data} ->
                {next_state, StateName, Data, 10000};
            {StateName, Data} ->
                {next_state, StateName, Data}
           end.
       -else.
       locked(cast, {button,Digit}, Data0) ->
           case analyze_lock(Digit, Data0) of
            {open = StateName, Data} ->
                {next_state, StateName, Data, 10000};
            {StateName, Data} ->
                {next_state, StateName, Data}
           end;
       locked({call, From}, Msg, Data) ->
           handle_call(From, Msg, Data);
       locked({info, Msg}, StateName, Data) ->
           handle_info(Msg, StateName, Data).
       %% Arity differs
       %% All state events are dispatched to handle_call and handle_info help
       %% functions. If you want to handle a call or cast event specifically
       %% for this state you would add a special clause for it above.
       -endif.

       -ifdef(BEFORE_REWRITE).
       open(timeout, State) ->
            do_lock(),
           {next_state, locked, State};
       open({button,_}, Data) ->
           {next_state, locked, Data}.
       -else.
       open(timeout, _, Data) ->
           do_lock(),
           {next_state, locked, Data};
       open(cast, {button,_}, Data) ->
           {next_state, locked, Data};
       open({call, From}, Msg, Data) ->
           handle_call(From, Msg, Data);
       open(info, Msg, Data) ->
           handle_info(Msg, open, Data).
       %% Arity differs
       %% All state events are dispatched to handle_call and handle_info help
       %% functions. If you want to handle a call or cast event specifically
       %% for this state you would add a special clause for it above.
       -endif.

       -ifdef(BEFORE_REWRITE).
       handle_sync_event(stop, _From, _StateName, Data) ->
           {stop, normal, ok, Data}.

       handle_event(Event, StateName, Data) ->
           {stop, {shutdown, {unexpected, Event, StateName}}, Data}.

       handle_info(Info, StateName, Data) ->
           {stop, {shutdown, {unexpected, Info, StateName}}, StateName, Data}.
       -else.
       -endif.

       terminate(_Reason, State, _Data) ->
           State =/= locked andalso do_lock(),
           ok.
       code_change(_Vsn, State, Data, _Extra) ->
           {ok, State, Data}.

       %% Internal functions
       -ifdef(BEFORE_REWRITE).
       -else.
       handle_call(From, stop, Data) ->
            {stop_and_reply, normal,  {reply, From, ok}, Data}.

       handle_info(Info, StateName, Data) ->
           {stop, {shutdown, {unexpected, Info, StateName}}, StateName, Data}.
       %% These are internal functions for handling all state events
       %% and not behaviour callbacks as in gen_fsm
       -endif.

       analyze_lock(Digit, #{code := Code, remaining := Remaining} = Data) ->
            case Remaining of
                [Digit] ->
                 do_unlock(),
                 {open,  Data#{remaining := Code}};
                [Digit|Rest] -> % Incomplete
                    {locked, Data#{remaining := Rest}};
                _Wrong ->
                    {locked, Data#{remaining := Code}}
            end.

       do_lock() ->
           io:format("Lock~n", []).
       do_unlock() ->
           io:format("Unlock~n", []).