Provided by: erlang-manpages_25.2.3+dfsg-1_all bug

NAME

       gen_statem - Generic state machine behavior.

DESCRIPTION

       gen_statem  provides  a  generic  state  machine  behaviour that for new code replaces its
       predecessor gen_fsm since Erlang/OTP 20.0. The gen_fsm behaviour remains in OTP "as is".

   Note:
       If you are new to gen_statem and want an overview of concepts and  operation  the  section
       gen_statem  Behaviour   located in the User's Guide  OTP Design Principles  is recommended
       to read before this reference manual, possibly  after  the  Description  section  you  are
       reading here.

       This  reference  manual  contains type descriptions generated from types in the gen_statem
       source code, so they are correct. However, the generated  descriptions  also  reflect  the
       type  hierarchy,  which  sometimes  makes  it  hard to get a good overview. If so, see the
       section gen_statem Behaviour  in the  OTP Design Principles  User's Guide.

   Note:

         * This behavior appeared in Erlang/OTP 19.0.

         *
            In OTP 19.1 a backwards incompatible change of the return  tuple  from  Module:init/1
           was made and the mandatory callback function Module:callback_mode/0 was introduced.

         *
            In OTP 20.0  generic time-outs  were added.

         *
            In OTP 22.1 time-out content update and explicit time-out cancel were added.

         *
            In   OTP   22.3   the   possibility  to  change  the  callback  module  with  actions
           change_callback_module, push_callback_module and pop_callback_module, was added.

       gen_statem has got the same features that gen_fsm had and adds some really useful:

         * Co-located state code

         * Arbitrary term state

         * Event postponing

         * Self-generated events

         * State time-out

         * Multiple generic named time-outs

         * Absolute time-out time

         * Automatic state enter calls

         *
            Reply from other state than the request, sys traceable

         * Multiple sys traceable replies

         * Changing the callback module

       Two callback modes are supported:

         * One for finite-state machines (gen_fsm like), which requires the state to be  an  atom
           and uses that state as the name of the current callback function.

         * One  that  allows the state to be any term and that uses one callback function for all
           states.

       The callback model(s) for gen_statem differs from the one for gen_fsm,  but  it  is  still
       fairly easy to  rewrite from  gen_fsm to gen_statem.

       A  generic  state  machine server process (gen_statem) implemented using this module has a
       standard set of interface functions and  includes  functionality  for  tracing  and  error
       reporting. It also fits into an OTP supervision tree. For more information, see OTP Design
       Principles.

       A gen_statem assumes all specific parts to be located in a  callback  module  exporting  a
       predefined  set  of  functions.  The  relationship  between the behavior functions and the
       callback functions is as follows:

       gen_statem module            Callback module
       -----------------            ---------------
       gen_statem:start
       gen_statem:start_monitor
       gen_statem:start_link -----> Module:init/1

       Server start or code change
                             -----> Module:callback_mode/0

       gen_statem:stop       -----> Module:terminate/3

       gen_statem:call
       gen_statem:cast
       gen_statem:send_request
       erlang:send
       erlang:'!'            -----> Module:StateName/3
                                    Module:handle_event/4

       -                     -----> Module:terminate/3

       -                     -----> Module:code_change/4

       Events are of different types, so the callback functions can know the origin of  an  event
       and how to respond.

       If  a  callback  function  fails or returns a bad value, the gen_statem terminates, unless
       otherwise stated. However, an exception of class throw is not regarded as an error but  as
       a valid return from all callback functions.

       The  state  callback for a specific state in a gen_statem is the callback function that is
       called for all events in this state. It is selected depending on which callback mode  that
       the callback module defines with the callback function Module:callback_mode/0.

       When  the  callback  mode is state_functions, the state must be an atom and is used as the
       state callback name; see Module:StateName/3. This co-locates all code for a specific state
       in  one  function as the gen_statem engine branches depending on state name. Note the fact
       that the callback function Module:terminate/3 makes the state name terminate  unusable  in
       this mode.

       When  the  callback mode is handle_event_function, the state can be any term and the state
       callback name is Module:handle_event/4. This makes it easy to branch depending on state or
       event  as you desire. Be careful about which events you handle in which states so that you
       do not accidentally postpone an event forever creating an infinite busy loop.

       When gen_statem receives a process message it is converted into an  event  and  the  state
       callback  is  called  with  the  event  as two arguments: type and content. When the state
       callback has processed the event it returns to gen_statem which does a  state  transition.
       If  this  state  transition is to a different state, that is: NextState =/= State, it is a
       state change.

       The state callback may return transition actions for  gen_statem  to  execute  during  the
       state transition, for example to reply to a gen_statem:call/2,3.

       One  of  the  possible transition actions is to postpone the current event. Then it is not
       retried in the current state. The gen_statem engine keeps a queue of events  divided  into
       the  postponed  events  and  the  events  still to process. After a state change the queue
       restarts with the postponed events.

       The gen_statem event queue model is sufficient to emulate the normal process message queue
       with  selective  receive.  Postponing an event corresponds to not matching it in a receive
       statement, and changing states corresponds to entering a new receive statement.

       The state callback can insert events using the transition actions next_event and  such  an
       event is inserted in the event queue as the next to call the state callback with. That is,
       as if it is the oldest incoming event. A dedicated event_type() internal can be  used  for
       such events making them impossible to mistake for external events.

       Inserting  an  event  replaces the trick of calling your own state handling functions that
       you often would have to resort to in, for example, gen_fsm to force processing an inserted
       event before others.

       The  gen_statem  engine  can  automatically  make a specialized call to the state callback
       whenever a new state is entered; see state_enter(). This is for writing code common to all
       state  entries.  Another  way  to  do  it  is  to  explicitly insert an event at the state
       transition, and/or to use a dedicated state transition function, but that is something you
       will have to remember at every state transition to the state(s) that need it.

   Note:
       If  you  in  gen_statem, for example, postpone an event in one state and then call another
       state callback of yours, you have not done a state change and hence the postponed event is
       not retried, which is logical but can be confusing.

       For the details of a state transition, see type transition_option().

       A  gen_statem  handles system messages as described in sys. The sys module can be used for
       debugging a gen_statem.

       Notice that a gen_statem does not trap exit signals automatically, this must be explicitly
       initiated in the callback module (by calling process_flag(trap_exit, true).

       Unless  otherwise  stated,  all  functions in this module fail if the specified gen_statem
       does not exist or if bad arguments are specified.

       The gen_statem process can go into hibernation; see proc_lib:hibernate/3. It is done  when
       a  state  callback or Module:init/1 specifies hibernate in the returned Actions list. This
       feature can be useful to reclaim process heap memory while the server is  expected  to  be
       idle  for  a  long  time.  However,  use this feature with care, as hibernation can be too
       costly to use after every event; see erlang:hibernate/3.

       There  is  also  a  server  start  option  {hibernate_after,   Timeout}   for   start/3,4,
       start_monitor/3,4,  start_link/3,4  or enter_loop/4,5,6, that may be used to automatically
       hibernate the server.

       If the gen_statem process terminates, e.g. as a result  of  a  function  in  the  callback
       module  returning  {stop,Reason},  an  exit  signal  with  this  Reason  is sent to linked
       processes and ports. See  Processes in the Reference Manual for  details  regarding  error
       handling using exit signals.

EXAMPLE

       The  following  example  shows  a  simple  pushbutton  model  for  a  toggling  pushbutton
       implemented with callback mode state_functions. You can push the button and it replies  if
       it  went  on  or  off, and you can ask for a count of how many times it has been pushed to
       switch on.

       The following is the complete callback module file pushbutton.erl:

       -module(pushbutton).
       -behaviour(gen_statem).

       -export([start/0,push/0,get_count/0,stop/0]).
       -export([terminate/3,code_change/4,init/1,callback_mode/0]).
       -export([on/3,off/3]).

       name() -> pushbutton_statem. % The registered server name

       %% API.  This example uses a registered name name()
       %% and does not link to the caller.
       start() ->
           gen_statem:start({local,name()}, ?MODULE, [], []).
       push() ->
           gen_statem:call(name(), push).
       get_count() ->
           gen_statem:call(name(), get_count).
       stop() ->
           gen_statem:stop(name()).

       %% Mandatory callback functions
       terminate(_Reason, _State, _Data) ->
           void.
       code_change(_Vsn, State, Data, _Extra) ->
           {ok,State,Data}.
       init([]) ->
           %% Set the initial state + data.  Data is used only as a counter.
           State = off, Data = 0,
           {ok,State,Data}.
       callback_mode() -> state_functions.

       %%% state callback(s)

       off({call,From}, push, Data) ->
           %% Go to 'on', increment count and reply
           %% that the resulting status is 'on'
           {next_state,on,Data+1,[{reply,From,on}]};
       off(EventType, EventContent, Data) ->
           handle_event(EventType, EventContent, Data).

       on({call,From}, push, Data) ->
           %% Go to 'off' and reply that the resulting status is 'off'
           {next_state,off,Data,[{reply,From,off}]};
       on(EventType, EventContent, Data) ->
           handle_event(EventType, EventContent, Data).

       %% Handle events common to all states
       handle_event({call,From}, get_count, Data) ->
           %% Reply with the current count
           {keep_state,Data,[{reply,From,Data}]};
       handle_event(_, _, Data) ->
           %% Ignore all other events
           {keep_state,Data}.

       The following is a shell session when running it:

       1> pushbutton:start().
       {ok,<0.36.0>}
       2> pushbutton:get_count().
       0
       3> pushbutton:push().
       on
       4> pushbutton:get_count().
       1
       5> pushbutton:push().
       off
       6> pushbutton:get_count().
       1
       7> pushbutton:stop().
       ok
       8> pushbutton:push().
       ** exception exit: {noproc,{gen_statem,call,[pushbutton_statem,push,infinity]}}
            in function  gen:do_for_proc/2 (gen.erl, line 261)
            in call from gen_statem:call/3 (gen_statem.erl, line 386)

       To   compare   styles,   here   follows   the   same   example   using    callback    mode
       handle_event_function,  or  rather  the  code  to  replace  after  function  init/1 of the
       pushbutton.erl example file above:

       callback_mode() -> handle_event_function.

       %%% state callback(s)

       handle_event({call,From}, push, off, Data) ->
           %% Go to 'on', increment count and reply
           %% that the resulting status is 'on'
           {next_state,on,Data+1,[{reply,From,on}]};
       handle_event({call,From}, push, on, Data) ->
           %% Go to 'off' and reply that the resulting status is 'off'
           {next_state,off,Data,[{reply,From,off}]};
       %%
       %% Event handling common to all states
       handle_event({call,From}, get_count, State, Data) ->
           %% Reply with the current count
           {next_state,State,Data,[{reply,From,Data}]};
       handle_event(_, _, State, Data) ->
           %% Ignore all other events
           {next_state,State,Data}.

DATA TYPES

       server_name() =
           {local, atom()} |
           {global, GlobalName :: term()} |
           {via, RegMod :: module(), Name :: term()}

              Name specification to use when starting a gen_statem server. See  start_link/3  and
              server_ref() below.

       server_ref() =
           pid() |
           (LocalName :: atom()) |
           {Name :: atom(), Node :: atom()} |
           {global, GlobalName :: term()} |
           {via, RegMod :: module(), ViaName :: term()}

              Server  specification  to  use  when addressing a gen_statem server. See call/2 and
              server_name() above.

              It can be:

                pid() | LocalName:
                  The gen_statem is locally registered.

                {Name,Node}:
                  The gen_statem is locally registered on another node.

                {global,GlobalName}:
                  The gen_statem is globally registered in global.

                {via,RegMod,ViaName}:
                  The gen_statem is registered in an alternative process registry.  The  registry
                  callback    module    RegMod    is   to   export   functions   register_name/2,
                  unregister_name/1, whereis_name/1, and send/2, which are  to  behave  like  the
                  corresponding functions in global. Thus, {via,global,GlobalName} is the same as
                  {global,GlobalName}.

       start_opt() =
           {timeout, Time :: timeout()} |
           {spawn_opt, [proc_lib:spawn_option()]} |
           enter_loop_opt()

              Options that can be used when starting a gen_statem server  through,  for  example,
              start_link/3.

       start_ret() = {ok, pid()} | ignore | {error, term()}

              Return   value   from   the   start()  and  start_link()  functions,  for  example,
              start_link/3.

       start_mon_ret() =
           {ok, {pid(), reference()}} | ignore | {error, term()}

              Return value from the start_monitor() functions.

       enter_loop_opt() =
           {hibernate_after, HibernateAfterTimeout :: timeout()} |
           {debug, Dbgs :: [sys:debug_option()]}

              Options that can be used when starting a gen_statem server through, enter_loop/4-6.

                hibernate_after:
                  HibernateAfterTimeout specifies that the gen_statem process awaits any  message
                  for  HibernateAfterTimeout  milliseconds  and  if  no  message is received, the
                  process goes into hibernation automatically (by calling proc_lib:hibernate/3).

                debug:
                  For every entry in Dbgs, the corresponding function in sys is called.

       from() = {To :: pid(), Tag :: reply_tag()}

              Destination  to  use   when   replying   through,   for   example,   the   action()
              {reply,From,Reply} to a process that has called the gen_statem server using call/2.

       reply_tag()

              A handle that associates a reply to the corresponding request.

       state() = state_name() | term()

              If  the  callback mode is handle_event_function, the state can be any term. After a
              state change (NextState =/= State), all postponed events are retried.

       state_name() = atom()

              If the callback mode is state_functions, the state must be an atom. After  a  state
              change (NextState =/= State), all postponed events are retried. Note that the state
              terminate is not possible to use since it would collide with the optional  callback
              function Module:terminate/3.

       data() = term()

              A  term  in  which  the state machine implementation is to store any server data it
              needs. The difference between this and the state() itself is that a change in  this
              data does not cause postponed events to be retried. Hence, if a change in this data
              would change the set of events that are handled, then that data item is to be  made
              a part of the state.

       event_type() =
           external_event_type() | timeout_event_type() | internal

              There are 3 categories of events: external, timeout, and internal.

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

       external_event_type() = {call, From :: from()} | cast | info

              External events are of 3 types: {call,From}, cast, or info.  Type  call  originates
              from  the  API  functions  call/2 and send_request/2. For calls, the event contains
              whom to reply to. Type cast originates from the  API  function  cast/2.  Type  info
              originates from regular process messages sent to the gen_statem.

       timeout_event_type() =
           timeout | {timeout, Name :: term()} | state_timeout

              There are 3 types of time-out events that the state machine can generate for itself
              with the corresponding timeout_action()s.

       event_content() = term()

              Any event's content can be any term.

              See event_type that describes the origins of the different event  types,  which  is
              also where the event content comes from.

       callback_mode_result() =
           callback_mode() | [callback_mode() | state_enter()]

              This  is  the return type from Module:callback_mode/0 and selects callback mode and
              whether to do state enter calls, or not.

       callback_mode() = state_functions | handle_event_function

              The callback mode is selected with the return value from Module:callback_mode/0:

                state_functions:
                  The state must be of type state_name() and one  callback  function  per  state,
                  that is, Module:StateName/3, is used.

                handle_event_function:
                  The  state  can  be any term and the callback function Module:handle_event/4 is
                  used for all states.

              The function Module:callback_mode/0 is called when starting the  gen_statem,  after
              code  change  and  after  changing  the  callback  module  with  any of the actions
              change_callback_module, push_callback_module or pop_callback_module. The result  is
              cached for subsequent calls to state callbacks.

       state_enter() = state_enter

              Whether  the  state  machine  should  use state enter calls or not is selected when
              starting the  gen_statem  and  after  code  change  using  the  return  value  from
              Module:callback_mode/0.

              If  Module:callback_mode/0  returns  a  list containing state_enter, the gen_statem
              engine will, at every state change, call the state callback with arguments  (enter,
              OldState,  Data) or (enter, OldState, State, Data), depending on the callback mode.
              This may look like an event but is really a call performed after the previous state
              callback  returned and before any event is delivered to the new state callback. See
              Module:StateName/3 and Module:handle_event/4.  Such  a  call  can  be  repeated  by
              returning a repeat_state or repeat_state_and_data tuple from the state callback.

              If  Module:callback_mode/0  does  not  return such a list, no state enter calls are
              done.

              If Module:code_change/4 should transform the state,  it  is  regarded  as  a  state
              rename and not a state change, which will not cause a state enter call.

              Note  that  a state enter call will be done right before entering the initial state
              even though this actually is not a state change. In this case OldState  =:=  State,
              which  cannot  happen for a subsequent state change, but will happen when repeating
              the state enter call.

       transition_option() =
           postpone() |
           hibernate() |
           event_timeout() |
           generic_timeout() |
           state_timeout()

              Transition options can be set by actions and modify the state transition. The state
              transition  takes place when the state callback has processed an event and returns.
              Here are the sequence of steps for a state transition:

                * All returned actions are processed in order of appearance.  In  this  step  all
                  replies   generated   by   any  reply_action()  are  sent.  Other  actions  set
                  transition_option()s that come into play in subsequent steps.

                * If state enter calls are used, and either it is the initial state or one of the
                  callback  results  repeat_state_and_data  or  repeat_state_and_data is used the
                  gen_statem engine calls the  current  state  callback  with  arguments  (enter,
                  State,  Data)  or  (enter, State, State, Data) (depending on callback mode) and
                  when it returns starts again from the top of this sequence.

                  If state enter calls are used, and the  state  changes  the  gen_statem  engine
                  calls  the new state callback with arguments (enter, OldState, Data) or (enter,
                  OldState, State, Data) (depending on callback mode) and when it returns  starts
                  again from the top of this sequence.

                * If postpone() is true, the current event is postponed.

                * If  this is a state change, the queue of incoming events is reset to start with
                  the oldest postponed.

                * All events stored with action() next_event are inserted to be processed  before
                  previously queued events.

                * Time-out  timers  event_timeout(),  generic_timeout()  and  state_timeout() are
                  handled. Time-outs with zero time are guaranteed to be delivered to  the  state
                  machine  before any external not yet received event so if there is such a time-
                  out requested, the corresponding time-out zero event is enqueued as the  newest
                  received  event;  that  is  after  already  queued  events such as inserted and
                  postponed events.

                  Any event cancels an event_timeout() so a zero  time  event  time-out  is  only
                  generated if the event queue is empty.

                  A  state change cancels a state_timeout() and any new transition option of this
                  type belongs to the new state, that is; a state_timeout() applies to the  state
                  the state machine enters.

                * If  there  are enqueued events the state callback for the possibly new state is
                  called with the oldest enqueued event, and we start again from the top of  this
                  sequence.

                * Otherwise  the  gen_statem  goes into receive or hibernation (if hibernate() is
                  true) to wait for the next message. In hibernation the  next  non-system  event
                  awakens  the  gen_statem,  or  rather  the  next  incoming  message awakens the
                  gen_statem, but if it is a system event it goes right  back  into  hibernation.
                  When  a new message arrives the state callback is called with the corresponding
                  event, and we start again from the top of this sequence.

       postpone() = boolean()

              If true, postpones the current event and retries it after a state change (NextState
              =/= State).

       hibernate() = boolean()

              If  true,  hibernates  the  gen_statem by calling proc_lib:hibernate/3 before going
              into receive to wait for a new external event.

          Note:
              If there are enqueued events to process  when  hibrnation  is  requested,  this  is
              optimized  by  not  hibernating  but  instead  calling  erlang:garbage_collect/0 to
              simulate that the gen_statem entered hibernation and immediately got awakened by an
              enqueued event.

       event_timeout() = timeout() | integer()

              Starts  a  timer  set by enter_action() timeout. When the timer expires an event of
              event_type() timeout will be generated. See erlang:start_timer/4 for how  Time  and
              Options  are  interpreted. Future erlang:start_timer/4 Options will not necessarily
              be supported.

              Any event that arrives cancels this time-out. Note that a retried or inserted event
              counts  as arrived. So does a state time-out zero event, if it was generated before
              this time-out is requested.

              If Time is infinity, no timer is started, as it never would expire anyway.

              If Time is relative and 0 no timer is actually started, instead  the  the  time-out
              event  is  enqueued  to  ensure  that it gets processed before any not yet received
              external event, but after already queued events.

              Note that it is not possible nor needed to cancel this time-out, as it is cancelled
              automatically by any other event.

       generic_timeout() = timeout() | integer()

              Starts  a  timer  set  by  enter_action() {timeout,Name}. When the timer expires an
              event of event_type() {timeout,Name} will be  generated.  See  erlang:start_timer/4
              for  how Time and Options are interpreted. Future erlang:start_timer/4 Options will
              not necessarily be supported.

              If Time is infinity, no timer is started, as it never would expire anyway.

              If Time is relative and 0 no timer is actually started, instead  the  the  time-out
              event  is  enqueued  to  ensure  that it gets processed before any not yet received
              external event.

              Setting a timer with the same Name while it is running will restart it with the new
              time-out  value.  Therefore it is possible to cancel a specific time-out by setting
              it to infinity.

       state_timeout() = timeout() | integer()

              Starts a timer set by enter_action() state_timeout. When the timer expires an event
              of  event_type()  state_timeout will be generated. See erlang:start_timer/4 for how
              Time and Options are interpreted.  Future  erlang:start_timer/4  Options  will  not
              necessarily be supported.

              If Time is infinity, no timer is started, as it never would expire anyway.

              If  Time  is  relative and 0 no timer is actually started, instead the the time-out
              event is enqueued to ensure that it gets processed  before  any  not  yet  received
              external event.

              Setting this timer while it is running will restart it with the new time-out value.
              Therefore it is possible to cancel this time-out by setting it to infinity.

       timeout_option() = {abs, Abs :: boolean()}

              If Abs is true an absolute timer is started, and if it is false a  relative,  which
              is the default. See erlang:start_timer/4 for details.

       action() =
           postpone |
           {postpone, Postpone :: postpone()} |
           {next_event,
            EventType :: event_type(),
            EventContent :: event_content()} |
           {change_callback_module, NewModule :: module()} |
           {push_callback_module, NewModule :: module()} |
           pop_callback_module |
           enter_action()

              These  transition  actions can be invoked by returning them from the state callback
              when it is  called  with  an  event,  from  Module:init/1  or  by  giving  them  to
              enter_loop/5,6.

              Actions are executed in the containing list order.

              Actions  that  set   transition options  override any previous of the same type, so
              the last in the containing list wins. For example, the  last  postpone()  overrides
              any previous postpone() in the list.

                postpone:
                  Sets  the transition_option() postpone() for this state transition. This action
                  is ignored when returned from Module:init/1  or  given  to  enter_loop/5,6,  as
                  there is no event to postpone in those cases.

                next_event:
                  This  action  does  not  set  any  transition_option()  but  instead stores the
                  specified EventType and EventContent for insertion after all actions have  been
                  executed.

                  The  stored  events are inserted in the queue as the next to process before any
                  already queued events. The order of these stored events is  preserved,  so  the
                  first next_event in the containing list becomes the first to process.

                  An  event  of type internal is to be used when you want to reliably distinguish
                  an event inserted this way from any external event.

                change_callback_module:
                  Changes the callback module to NewModule which will be used  when  calling  all
                  subsequent state callbacks.

                  The  gen_statem  engine will find out the callback mode of NewModule by calling
                  NewModule:callback_mode/0 before the next state callback.

                  Changing the callback module does not affect the state transition in  any  way,
                  it  only  changes  which  module  that  handles  the  events. Be aware that all
                  relevant  callback  functions  in  NewModule  such  as  the   state   callback,
                  NewModule:code_change/4,  NewModule:format_status/1  and  NewModule:terminate/3
                  must be able to handle the state and data from the old module.

                push_callback_module:
                  Pushes the current callback module to the top of an internal stack of  callback
                  modules   and   changes  the  callback  module  to  NewModule.  Otherwise  like
                  {change_callback_module, NewModule} above.

                pop_callback_module:
                   Pops the top module from the internal stack of callback  modules  and  changes
                  the  callback  module to be the popped module. If the stack is empty the server
                  fails. Otherwise like {change_callback_module, NewModule} above.

       enter_action() =
           hibernate |
           {hibernate, Hibernate :: hibernate()} |
           timeout_action() |
           reply_action()

              These transition actions can be invoked by returning them from the state  callback,
              from Module:init/1 or by giving them to enter_loop/5,6.

              Actions are executed in the containing list order.

              Actions  that set transition options override any previous of the same type, so the
              last in the containing list wins. For example, the last  event_timeout()  overrides
              any previous event_timeout() in the list.

                hibernate:
                  Sets the transition_option() hibernate() for this state transition.

       timeout_action() =
           (Time :: event_timeout()) |
           {timeout,
            Time :: event_timeout(),
            EventContent :: event_content()} |
           {timeout,
            Time :: event_timeout(),
            EventContent :: event_content(),
            Options :: timeout_option() | [timeout_option()]} |
           {{timeout, Name :: term()},
            Time :: generic_timeout(),
            EventContent :: event_content()} |
           {{timeout, Name :: term()},
            Time :: generic_timeout(),
            EventContent :: event_content(),
            Options :: timeout_option() | [timeout_option()]} |
           {state_timeout,
            Time :: state_timeout(),
            EventContent :: event_content()} |
           {state_timeout,
            Time :: state_timeout(),
            EventContent :: event_content(),
            Options :: timeout_option() | [timeout_option()]} |
           timeout_cancel_action() |
           timeout_update_action()

              These  transition actions can be invoked by returning them from the state callback,
              from Module:init/1 or by giving them to enter_loop/5,6.

              These time-out actions sets time-out transition options.

                Time:
                  Short for {timeout,Time,Time}, that is, the time-out message  is  the  time-out
                  time.   This   form   exists   to   make   the   state  callback  return  value
                  {next_state,NextState,NewData,Time} allowed like for gen_fsm.

                timeout:
                  Sets the transition_option() event_timeout()  to  Time  with  EventContent  and
                  time-out options Options.

                {timeout,Name}:
                  Sets   the   transition_option()   generic_timeout()  to  Time  for  Name  with
                  EventContent and time-out options Options.

                state_timeout:
                  Sets the transition_option() state_timeout()  to  Time  with  EventContent  and
                  time-out options Options.

       timeout_cancel_action() =
           {timeout, cancel} |
           {{timeout, Name :: term()}, cancel} |
           {state_timeout, cancel}

              This is a shorter and clearer form of  timeout_action()  with Time = infinity which
              cancels a time-out.

       timeout_update_action() =
           {timeout, update, EventContent :: event_content()} |
           {{timeout, Name :: term()},
            update,
            EventContent :: event_content()} |
           {state_timeout, update, EventContent :: event_content()}

              Updates a time-out with a new EventContent. See  timeout_action()  for how to start
              a time-out.

              If  no  time-out  of the same type is active instead insert the time-out event just
              like when starting a time-out with relative Time = 0.

       reply_action() = {reply, From :: from(), Reply :: term()}

              This transition action can be invoked by returning it from the state callback, from
              Module:init/1 or by giving it to enter_loop/5,6.

              It does not set any transition_option() but instead replies to a caller waiting for
              a reply in call/2. From must be the term from argument {call,From} in a call  to  a
              state callback.

              Note  that using this action from Module:init/1 or enter_loop/5,6 would be weird on
              the border of witchcraft since there has been no earlier call to a  state  callback
              in this server.

       init_result(StateType) = init_result(StateType, term())

       init_result(StateType, DataType) =
           {ok, State :: StateType, Data :: DataType} |
           {ok,
            State :: StateType,
            Data :: DataType,
            Actions :: [action()] | action()} |
           ignore |
           {stop, Reason :: term()}

              For  a  succesful initialization, State is the initial state() and Data the initial
              server data() of the gen_statem.

              The Actions are executed when  entering  the  first  state  just  as  for  a  state
              callback,  except  that  the  action  postpone is forced to false since there is no
              event to postpone.

              For an unsuccesful initialization, {stop,Reason} or  ignore  should  be  used;  see
              start_link/3,4.

       state_enter_result(State) = state_enter_result(State, term())

       state_enter_result(State, DataType) =
           {next_state, State, NewData :: DataType} |
           {next_state, State,
            NewData :: DataType,
            Actions :: [enter_action()] | enter_action()} |
           state_callback_result(enter_action())

              State  is  the  current state and it cannot be changed since the state callback was
              called with a state enter call.

                next_state:
                  The gen_statem does a state transition to State, which has to  be  the  current
                  state, sets NewData, and executes all Actions.

       event_handler_result(StateType) =
           event_handler_result(StateType, term())

       event_handler_result(StateType, DataType) =
           {next_state, NextState :: StateType, NewData :: DataType} |
           {next_state,
            NextState :: StateType,
            NewData :: DataType,
            Actions :: [action()] | action()} |
           state_callback_result(action())

              StateType  is  state_name()  if  callback  mode  is  state_functions, or state() if
              callback mode is handle_event_function.

                next_state:
                  The gen_statem does a state transition to NextState (which can be the  same  as
                  the  current  state),  sets NewData, and executes all Actions. If NextState =/=
                  CurrentState the state transition is a state change.

       state_callback_result(ActionType) =
           state_callback_result(ActionType, term())

       state_callback_result(ActionType, DataType) =
           {keep_state, NewData :: DataType} |
           {keep_state,
            NewData :: DataType,
            Actions :: [ActionType] | ActionType} |
           keep_state_and_data |
           {keep_state_and_data, Actions :: [ActionType] | ActionType} |
           {repeat_state, NewData :: DataType} |
           {repeat_state,
            NewData :: DataType,
            Actions :: [ActionType] | ActionType} |
           repeat_state_and_data |
           {repeat_state_and_data, Actions :: [ActionType] | ActionType} |
           stop |
           {stop, Reason :: term()} |
           {stop, Reason :: term(), NewData :: DataType} |
           {stop_and_reply,
            Reason :: term(),
            Replies :: [reply_action()] | reply_action()} |
           {stop_and_reply,
            Reason :: term(),
            Replies :: [reply_action()] | reply_action(),
            NewData :: DataType}

              ActionType is enter_action() if the state callback was called with  a  state  enter
              call and action() if the state callback was called with an event.

                keep_state:
                  The same as {next_state,CurrentState,NewData,Actions}.

                keep_state_and_data:
                  The same as {keep_state,CurrentData,Actions}.

                repeat_state:
                  If  the  gen_statem  runs  with  state  enter  calls,  the  state enter call is
                  repeated, see type transition_option(), other than  that  repeat_state  is  the
                  same as keep_state.

                repeat_state_and_data:
                  The same as {repeat_state,CurrentData,Actions}.

                stop:
                  Terminates  the  gen_statem  by  calling  Module:terminate/3  with  Reason  and
                  NewData, if specified. An exit signal  with  this  reason  is  sent  to  linked
                  processes and ports. The default Reason is normal.

                stop_and_reply:
                  Sends all Replies, then terminates the gen_statem by calling Module:terminate/3
                  with Reason and NewData, if specified. An exit signal with this reason is  sent
                  to linked processes and ports.

              All  these  terms  are  tuples  or  atoms and this property will hold in any future
              version of gen_statem.

       request_id()

              An opaque request identifier. See send_request/2 for details.

       request_id_collection()

              An opaque collection of  request  identifiers  (request_id())  where  each  request
              identifier  can be associated with a label chosen by the user. For more information
              see reqids_new/0.

       response_timeout() = timeout() | {abs, integer()}

              Used to set a time  limit  on  how  long  to  wait  for  a  response  using  either
              receive_response/2,  receive_response/3,  wait_response/2,  or wait_response/3. The
              time unit used is millisecond. Currently valid values:

                0..4294967295:
                  Timeout relative to current time in milliseconds.

                infinity:
                  Infinite timeout. That is, the operation will never time out.

                {abs, Timeout}:
                  An absolute Erlang  monotonic  time  timeout  in  milliseconds.  That  is,  the
                  operation will time out when erlang:monotonic_time(millisecond) returns a value
                  larger than or equal to Timeout. Timeout is not  allowed  to  identify  a  time
                  further  into  the future than 4294967295 milliseconds. Identifying the timeout
                  using an absolute timeout value is especially handy when you  have  a  deadline
                  for   responses   corresponding   to   a   complete   collection   of  requests
                  (request_id_collection()) , since you do not have to recalculate  the  relative
                  time until the deadline over and over again.

       format_status() =
           #{state => state(),
             data => data(),
             reason => term(),
             queue => [{event_type(), event_content()}],
             postponed => [{event_type(), event_content()}],
             timeouts => [{timeout_event_type(), event_content()}],
             log => [sys:system_event()]}

              A map that describes the gen_statem status. The keys are:

                state:
                  The current state of the gen_statem process.

                data:
                  The state data of the the gen_statem process.

                reason:
                  The reason that caused the state machine to terminate.

                queue:
                  The event queue of the gen_statem process.

                postponed:
                   The postponed events queue of the gen_statem process.

                timeouts:
                   The active time-outs of the gen_statem process.

                log:
                   The sys log of the server.

              New associations may be added to the status map without prior notice.

EXPORTS

       call(ServerRef :: server_ref(), Request :: term()) ->
               Reply :: term()

       call(ServerRef :: server_ref(),
            Request :: term(),
            Timeout ::
                timeout() |
                {clean_timeout, T :: timeout()} |
                {dirty_timeout, T :: timeout()}) ->
               Reply :: term()

              Makes  a  synchronous  call  to  the  gen_statem ServerRef by sending a request and
              waiting until its reply arrives. The  gen_statem  calls  the  state  callback  with
              event_type() {call,From} and event content Request.

              A  Reply  is generated when a state callback returns with {reply,From,Reply} as one
              action(), and that Reply becomes the return value of this function.

              Timeout is an integer > 0, which specifies how many  milliseconds  to  wait  for  a
              reply, or the atom infinity to wait indefinitely, which is the default. If no reply
              is received within the specified time, the function call fails.

          Note:
              For Timeout < infinity, to avoid getting a late reply in the caller's inbox if  the
              caller  should catch exceptions, this function spawns a proxy process that does the
              call. A late reply gets delivered to the dead proxy process, hence gets  discarded.
              This is less efficient than using Timeout == infinity.

              Timeout  can also be a tuple {clean_timeout,T} or {dirty_timeout,T}, where T is the
              time-out time. {clean_timeout,T} works like just T described in the note above  and
              uses  a  proxy  process while {dirty_timeout,T} bypasses the proxy process which is
              more lightweight.

          Note:
              If you combine catching exceptions from this  function  with  {dirty_timeout,T}  to
              avoid  that  the  calling process dies when the call times out, you will have to be
              prepared to handle a late reply. Note that there is an odd chance  to  get  a  late
              reply  even  with  {dirty_timeout,infinity} or infinity for example in the event of
              network problems. So why not just let the calling process die by not  catching  the
              exception?

              The  call  can also fail, for example, if the gen_statem dies before or during this
              function call.

              When this call fails it exits the calling process. The exit term  is  on  the  form
              {Reason,    Location}    where    Location    =    {gen_statem,call,ArgList}.   See
              gen_server:call/3 that has a description of relevant values for the Reason  in  the
              exit term.

       cast(ServerRef :: server_ref(), Msg :: term()) -> ok

              Sends an asynchronous event to the gen_statem ServerRef and returns ok immediately,
              ignoring if the destination node or gen_statem does not exist. The gen_statem calls
              the state callback with event_type() cast and event content Msg.

       check_response(Msg, ReqId) -> Result

              Types:

                 Msg = term()
                 ReqId = request_id()
                 Response =
                     {reply, Reply :: term()} |
                     {error, {Reason :: term(), server_ref()}}
                 Result = Response | no_reply

              Check  if  Msg  is  a  response  corresponding to the request identifier ReqId. The
              request must have been made by send_request/2. If Msg is  a  reply  to  the  handle
              ReqId  the  result  of the request is returned in Reply. Otherwise returns no_reply
              and no cleanup is done, and thus the function shall be invoked repeatedly  until  a
              reply is returned.

              The   return   value  Reply  is  generated  when  a  state  callback  returns  with
              {reply,From,Reply} as one action(), and that Reply becomes the return value of this
              function.

              The function returns an error if the gen_statem dies before or during this request.

       check_response(Msg, ReqIdCollection, Delete) -> Result

              Types:

                 Msg = term()
                 ReqIdCollection = request_id_collection()
                 Delete = boolean()
                 Response =
                     {reply, Reply :: term()} |
                     {error, {Reason :: term(), server_ref()}}
                 Result =
                     {Response,
                      Label :: term(),
                      NewReqIdCollection :: request_id_collection()} |
                     no_request | no_reply

              Check  if  Msg  is  a  response  corresponding  to  a  request  identifier saved in
              ReqIdCollection. All request identifiers  of  ReqIdCollection  must  correspond  to
              requests  that  have  been  made  using  send_request/2  or send_request/4, and all
              request must have been made by the process calling this function.

              The Label in the response equals the Label associated with the  request  identifier
              that  the  response corresponds to. The Label of a request identifier is associated
              when saving the request id in a request identifier collection, or when sending  the
              request using send_request/4.

              Compared  to  check_response/2,  the  returned  result  associated  with a specific
              request identifier or an exception associated with a  specific  request  identifier
              will be wrapped in a 3-tuple. The first element of this tuple equals the value that
              would have been produced by check_response/2, the second element equals  the  Label
              associated   with   the   specific   request  identifier,  and  the  third  element
              NewReqIdCollection is a possibly modified request identifier collection.

              If ReqIdCollection is empty, the atom no_request will be returned. If Msg does  not
              correspond  to any of the request identifiers in ReqIdCollection, the atom no_reply
              is returned.

              If Delete equals true, the association with  Label  will  have  been  deleted  from
              ReqIdCollection  in  the  resulting  NewReqIdCollection.  If  Delete  equals false,
              NewReqIdCollection will equal ReqIdCollection. Note that deleting an association is
              not for free and that a collection containing already handled requests can still be
              used   by   subsequent   calls   to   check_response/3,   receive_response/3,   and
              wait_response/3.  However,  without  deleting handled associations, the above calls
              will not be able to detect when there are no more outstanding requests  to  handle,
              so  you will have to keep track of this some other way than relying on a no_request
              return. Note that if you pass a collection only containing associations of  already
              handled or abandoned requests to check_response/3, it will always return no_reply.

       enter_loop(Module :: module(),
                  Opts :: [enter_loop_opt()],
                  State :: state(),
                  Data :: data()) ->
                     no_return()

              The  same  as enter_loop/6 with Actions = [] except that no server_name() must have
              been registered. This creates an anonymous server.

       enter_loop(Module :: module(),
                  Opts :: [enter_loop_opt()],
                  State :: state(),
                  Data :: data(),
                  Server_or_Actions :: server_name() | pid() | [action()]) ->
                     no_return()

              If Server_or_Actions  is  a  list(),  the  same  as  enter_loop/6  except  that  no
              server_name()  must  have  been  registered  and  Actions = Server_or_Actions. This
              creates an anonymous server.

              Otherwise the same as enter_loop/6 with Server = Server_or_Actions  and  Actions  =
              [].

       enter_loop(Module :: module(),
                  Opts :: [enter_loop_opt()],
                  State :: state(),
                  Data :: data(),
                  Server :: server_name() | pid(),
                  Actions :: [action()] | action()) ->
                     no_return()

              Makes the calling process become a gen_statem. Does not return, instead the calling
              process enters the gen_statem receive loop and becomes  a  gen_statem  server.  The
              process  must  have  been started using one of the start functions in proc_lib. The
              user is responsible for any initialization of the process, including registering  a
              name for it.

              This function is useful when a more complex initialization procedure is needed than
              the gen_statem behavior provides.

              Module, Opts have the same meaning as when calling start[_link|_monitor]/3,4.

              If  Server  is  self()  an  anonymous  server  is  created  just  as   when   using
              start[_link|_monitor]/3.  If  Server  is  a server_name() a named server is created
              just as when using start[_link|_monitor]/4. However, the  server_name()  name  must
              have been registered accordingly before this function is called.

              State,  Data,  and  Actions  have  the  same  meanings  as  in  the return value of
              Module:init/1. Also, the callback module does not need to  export  a  Module:init/1
              function.

              The  function  fails  if  the  calling  process was not started by a proc_lib start
              function, or if it is not registered according to server_name().

       receive_response(ReqId) -> Result

              Types:

                 ReqId = request_id()
                 Response =
                     {reply, Reply :: term()} |
                     {error, {Reason :: term(), server_ref()}}
                 Result = Response | timeout

              The same as calling gen_statem:receive_response(ReqId, infinity).

       receive_response(ReqId, Timeout) -> Result

              Types:

                 ReqId = request_id()
                 Timeout = response_timeout()
                 Response =
                     {reply, Reply :: term()} |
                     {error, {Reason :: term(), server_ref()}}
                 Result = Response | timeout

              Receive a response corresponding to the request identifier ReqId- The request  must
              have  been  made by send_request/2 to the gen_statem process. This function must be
              called from the same process from which send_request/2 was made.

              Timeout specifies how long to wait for a  response.  If  no  response  is  received
              within  the  specified time, the function returns timeout. Assuming that the server
              executes on a node supporting aliases (introduced in OTP 24) the request will  also
              be  abandoned.  That is, no response will be received after a timeout. Otherwise, a
              stray response might be received at a later time.

              The  return  value  Reply  is  generated  when  a  state  callback   returns   with
              {reply,From,Reply} as one action(), and that Reply becomes the return value of this
              function.

              The function returns an error if the gen_statem dies before or during this function
              call.

              The   difference   between   wait_response/2   and   receive_response/2   is   that
              receive_response/2 abandons the request at  timeout  so  that  a  potential  future
              response is ignored, while wait_response/2 does not.

       receive_response(ReqIdCollection, Timeout, Delete) -> Result

              Types:

                 ReqIdCollection = request_id_collection()
                 Timeout = response_timeout()
                 Delete = boolean()
                 Response =
                     {reply, Reply :: term()} |
                     {error, {Reason :: term(), server_ref()}}
                 Result =
                     {Response,
                      Label :: term(),
                      NewReqIdCollection :: request_id_collection()} |
                     no_request | timeout

              Receive  a response corresponding to a request identifier saved in ReqIdCollection.
              All request identifiers of ReqIdCollection must correspond to  requests  that  have
              been  made  using  send_request/2 or send_request/4, and all request must have been
              made by the process calling this function.

              The Label in the response equals the Label associated with the  request  identifier
              that  the  response corresponds to. The Label of a request identifier is associated
              when adding the request id in a request identifier collection, or when sending  the
              request using send_request/4.

              Compared  to  receive_response/2,  the  returned  result associated with a specific
              request identifier will be wrapped in a 3-tuple. The first element  of  this  tuple
              equals  the  value  that would have been produced by receive_response/2, the second
              element equals the Label associated with the specific request identifier,  and  the
              third   element  NewReqIdCollection  is  a  possibly  modified  request  identifier
              collection.

              If ReqIdCollection is empty, the atom no_request will be returned.

              Timeout specifies how long to wait for a  response.  If  no  response  is  received
              within  the  specified time, the function returns timeout. Assuming that the server
              executes on  a  node  supporting  aliases  (introduced  in  OTP  24)  all  requests
              identified by ReqIdCollection will also be abandoned. That is, no responses will be
              received after a timeout. Otherwise, stray responses might be received at  a  later
              time.

              The   difference   between   receive_response/3   and   wait_response/3   is   that
              receive_response/3 abandons the  requests  at  timeout  so  that  potential  future
              responses are ignored, while wait_response/3 does not.

              If  Delete  equals  true,  the  association  with Label will have been deleted from
              ReqIdCollection in  the  resulting  NewReqIdCollection.  If  Delete  equals  false,
              NewReqIdCollection will equal ReqIdCollection. Note that deleting an association is
              not for free and that a collection containing already handled requests can still be
              used   by   subsequent   calls   to   receive_response/3,   check_response/3,   and
              wait_response/3. However, without deleting handled associations,  the  above  calls
              will  not  be able to detect when there are no more outstanding requests to handle,
              so you will have to keep track of this some other way than relying on a  no_request
              return.  Note that if you pass a collection only containing associations of already
              handled or abandoned requests to receive_response/3, it will always block  until  a
              timeout determined by Timeout is triggered.

       reply(Replies :: [reply_action()] | reply_action()) -> ok

       reply(From :: from(), Reply :: term()) -> ok

              This  function  can be used by a gen_statem to explicitly send a reply to a process
              that waits in call/2 when the reply cannot be defined in  the  return  value  of  a
              state callback.

              From  must  be the term from argument {call,From} to the state callback. A reply or
              multiple replies canalso be sent using one or several reply_action()s from a  state
              callback.

          Note:
              A reply sent with this function is not visible in sys debug output.

       reqids_add(ReqId :: request_id(),
                  Label :: term(),
                  ReqIdCollection :: request_id_collection()) ->
                     NewReqIdCollection :: request_id_collection()

              Saves  ReqId  and  associates  a  Label  with the request identifier by adding this
              information to ReqIdCollection  and  returning  the  resulting  request  identifier
              collection.

       reqids_new() -> NewReqIdCollection :: request_id_collection()

              Returns  a new empty request identifier collection. A request identifier collection
              can be utilized in order the handle multiple outstanding requests.

              Request identifiers of requests made by send_request/2 can be saved  in  a  request
              identifier  collection using reqids_add/3. Such a collection of request identifiers
              can later be used in order to get one response corresponding to a  request  in  the
              collection   by   passing   the   collection  as  argument  to  receive_response/3,
              wait_response/3, or, check_response/3.

              reqids_size/1 can be used to determine the  amount  of  request  identifiers  in  a
              request identifier collection.

       reqids_size(ReqIdCollection :: request_id_collection()) ->
                      integer() >= 0

              Returns the amount of request identifiers saved in ReqIdCollection.

       reqids_to_list(ReqIdCollection :: request_id_collection()) ->
                         [{ReqId :: request_id(), Label :: term()}]

              Returns  a  list  of  {ReqId,  Label}  tuples  which  corresponds  to  all  request
              identifiers with their associated labels present in the ReqIdCollection collection.

       send_request(ServerRef :: server_ref(), Request :: term()) ->
                       ReqId :: request_id()

              Sends an asynchronous call request Request to the gen_statem process identified  by
              ServerRef  and  returns  a  request  identifier ReqId. The return value ReqId shall
              later be used with  receive_response/2,  wait_response/2,  or  check_response/2  to
              fetch  the  actual  result  of  the request. Besides passing the request identifier
              directly to these  functions,  it  can  also  be  saved  in  a  request  identifier
              collection  using  reqids_add/3. Such a collection of request identifiers can later
              be used in order to get one response corresponding to a request in  the  collection
              by  passing  the  collection as argument to receive_response/3, wait_response/3, or
              check_response/3. If you are about to save the  request  identifier  in  a  request
              identifier collection, you may want to consider using send_request/4 instead.

              The    call    gen_statem:wait_response(gen_statem:send_request(ServerRef,Request),
              Timeout) can be  seen  as  equivalent  to  gen_statem:call(Server,Request,Timeout),
              ignoring the error handling.

              The  gen_statem  calls  the  state callback with event_type() {call,From} and event
              content Request.

              A Reply is generated when a state callback returns with {reply,From,Reply}  as  one
              action(),  and  that  Reply  becomes  the  return  value  of  receive_response/1,2,
              wait_response/1,2, or check_response/2 function.

       send_request(ServerRef :: server_ref(),
                    Request :: term(),
                    Label :: term(),
                    ReqIdCollection :: request_id_collection()) ->
                       NewReqIdCollection :: request_id_collection()

              Sends an asynchronous call request Request to the gen_statem process identified  by
              ServerRef.  The  Label  will  be  associated  with  the  request  identifier of the
              operation   and   added   to   the   returned   request    identifier    collection
              NewReqIdCollection.  The  collection can later be used in order to get one response
              corresponding to a request in the collection by passing the collection as  argument
              to receive_response/3, wait_response/3, or, check_response/3.

              The  same as calling gen_statem:reqids_add(statem:send_request(ServerRef, Request),
              Label, ReqIdCollection), but calling send_request/4 is slightly more efficient.

       start(Module :: module(), Args :: term(), Opts :: [start_opt()]) ->
                start_ret()

       start(ServerName :: server_name(),
             Module :: module(),
             Args :: term(),
             Opts :: [start_opt()]) ->
                start_ret()

              Creates a standalone gen_statem process according to OTP design  principles  (using
              proc_lib  primitives). As it does not get linked to the calling process, this start
              function cannot be used by a supervisor to start a child.

              For a description of arguments and return values, see start_link/3,4.

       start_link(Module :: module(),
                  Args :: term(),
                  Opts :: [start_opt()]) ->
                     start_ret()

       start_link(ServerName :: server_name(),
                  Module :: module(),
                  Args :: term(),
                  Opts :: [start_opt()]) ->
                     start_ret()

              Creates a gen_statem process according to OTP  design  principles  (using  proc_lib
              primitives)  that  is  linked  to  the  calling process. This is essential when the
              gen_statem must be part of a supervision tree so it gets linked to its supervisor.

              The gen_statem process calls Module:init/1 to initialize the server.  To  ensure  a
              synchronized  startup procedure, start_link/3,4 does not return until Module:init/1
              has returned.

              ServerName specifies the server_name() to  register  for  the  gen_statem.  If  the
              gen_statem  is  started  with  start_link/3,  no  ServerName  is  provided  and the
              gen_statem is not registered.

              Module is the name of the callback module.

              Args is an arbitrary term that is passed as the argument to Module:init/1.

                * If option {timeout,Time} is present in Opts, the gen_statem is allowed to spend
                  Time  milliseconds initializing or it terminates and the start function returns
                  {error,timeout}.

                * If option {hibernate_after,HibernateAfterTimeout} is  present,  the  gen_statem
                  process  awaits  any  message  for HibernateAfterTimeout milliseconds and if no
                  message is received,  the  process  goes  into  hibernation  automatically  (by
                  calling proc_lib:hibernate/3).

                * If option {debug,Dbgs} is present in Opts, debugging through sys is activated.

                * If  option  {spawn_opt,SpawnOpts}  is  present  in Opts, SpawnOpts is passed as
                  option list to erlang:spawn_opt/2,  which  is  used  to  spawn  the  gen_statem
                  process.

          Note:
              Using  spawn  option  monitor  is not allowed, it causes this function to fail with
              reason badarg.

              If the gen_statem is successfully created and initialized,  this  function  returns
              {ok,Pid}, where Pid is the pid() of the gen_statem. If a process with the specified
              ServerName exists already,  this  function  returns  {error,{already_started,Pid}},
              where Pid is the pid() of that process.

              If  Module:init/1  fails  with  Reason,  this  function  returns {error,Reason}. If
              Module:init/1 returns {stop,Reason} or ignore, the process is terminated  and  this
              function  returns  {error,Reason}  or ignore, respectively. An exit signal with the
              same Reason (or normal if Module:init/1 returns ignore) is set to linked  processes
              and ports, including the process calling start_link/3,4.

       start_monitor(Module :: module(),
                     Args :: term(),
                     Opts :: [start_opt()]) ->
                        start_mon_ret()

       start_monitor(ServerName :: server_name(),
                     Module :: module(),
                     Args :: term(),
                     Opts :: [start_opt()]) ->
                        start_mon_ret()

              Creates  a  standalone gen_statem process according to OTP design principles (using
              proc_lib primitives) and atomically sets up a monitor to the newly created process.
              As  it  does  not  get linked to the calling process, this start function cannot be
              used by a supervisor to start a child.

              For a description of arguments and return values, see start_link/3,4. Note that the
              return  value  on  successful  start differs from start_link/3,4. start_monitor/3,4
              will return {ok,{Pid,Mon}} where Pid is the process identifier of the process,  and
              Mon  is  a  reference to the monitor set up to monitor the process. If the start is
              not successful, the caller will be blocked until the DOWN message has been received
              and removed from the message queue.

       stop(ServerRef :: server_ref()) -> ok

              The same as stop(ServerRef, normal, infinity).

       stop(ServerRef :: server_ref(),
            Reason :: term(),
            Timeout :: timeout()) ->
               ok

              Orders  the gen_statem ServerRef to exit with the specified Reason and waits for it
              to terminate. The gen_statem calls Module:terminate/3 before exiting.

              This function returns ok if the server terminates with  the  expected  reason.  Any
              other reason than normal, shutdown, or {shutdown,Term} causes an error report to be
              issued through logger(3erl). An exit signal with the same reason is sent to  linked
              processes and ports. The default Reason is normal.

              Timeout  is  an  integer > 0, which specifies how many milliseconds to wait for the
              server to terminate, or  the  atom  infinity  to  wait  indefinitely.  Defaults  to
              infinity.  If  the  server  does  not terminate within the specified time, the call
              exits the calling process with reason timeout.

              If the process does not exist, the call  exits  the  calling  process  with  reason
              noproc,  and with reason {nodedown,Node} if the connection fails to the remote Node
              where the server runs.

       wait_response(ReqId) -> Result

              Types:

                 ReqId = request_id()
                 Response =
                     {reply, Reply :: term()} |
                     {error, {Reason :: term(), server_ref()}}
                 Result = Response | timeout

              The same as calling gen_statem:receive_response(ReqId, infinity).

       wait_response(ReqId, WaitTime) -> Result

              Types:

                 ReqId = request_id()
                 WaitTime = response_timeout()
                 Response =
                     {reply, Reply :: term()} |
                     {error, {Reason :: term(), server_ref()}}
                 Result = Response | timeout

              Wait for a response corresponding to the request identifier ReqId. The request must
              have  been  made by send_request/2 to the gen_statem process. This function must be
              called from the same process from which send_request/2 was made.

              WaitTime specifies how long to wait for a reply. If no reply is received within the
              specified  time,  the function returns timeout and no cleanup is done, and thus the
              function can be invoked repeatedly until a reply is returned.

              The  return  value  Reply  is  generated  when  a  state  callback   returns   with
              {reply,From,Reply} as one action(), and that Reply becomes the return value of this
              function.

              The function returns an error if the gen_statem dies before or during this function
              call.

              The   difference   between   receive_response/2   and   wait_response/2   is   that
              receive_response/2 abandons the request at  timeout  so  that  a  potential  future
              response is ignored, while wait_response/2 does not.

       wait_response(ReqIdCollection, WaitTime, Delete) -> Result

              Types:

                 ReqIdCollection = request_id_collection()
                 WaitTime = response_timeout()
                 Delete = boolean()
                 Response =
                     {reply, Reply :: term()} |
                     {error, {Reason :: term(), server_ref()}}
                 Result =
                     {Response,
                      Label :: term(),
                      NewReqIdCollection :: request_id_collection()} |
                     no_request | timeout

              Wait for a response corresponding to a request identifier saved in ReqIdCollection.
              All request identifiers of ReqIdCollection must correspond to  requests  that  have
              been  made  using  send_request/2 or send_request/4, and all request must have been
              made by the process calling this function.

              The Label in the response equals the Label associated with the  request  identifier
              that  the  response corresponds to. The Label of a request identifier is associated
              when saving the request id in a request identifier collection, or when sending  the
              request using send_request/4.

              Compared to wait_response/2, the returned result associated with a specific request
              identifier or an exception associated with a specific request  identifier  will  be
              wrapped  in  a 3-tuple. The first element of this tuple equals the value that would
              have been  produced  by  wait_response/2,  the  second  element  equals  the  Label
              associated   with   the   specific   request  identifier,  and  the  third  element
              NewReqIdCollection is a possibly modified request identifier collection.

              If ReqIdCollection is empty,  no_request  will  be  returned.  If  no  response  is
              received  before  the WaitTime timeout has triggered, the atom timeout is returned.
              It is valid to continue waiting for a response as many times as needed up  until  a
              response  has  been received and completed by check_response(), receive_response(),
              or wait_response().

              The   difference   between   receive_response/3   and   wait_response/3   is   that
              receive_response/3  abandons  requests  at  timeout  so  that  a  potential  future
              responses are ignored, while wait_response/3 does not.

              If Delete equals true, the association with  Label  will  have  been  deleted  from
              ReqIdCollection  in  the  resulting  NewReqIdCollection.  If  Delete  equals false,
              NewReqIdCollection will equal ReqIdCollection. Note that deleting an association is
              not for free and that a collection containing already handled requests can still be
              used   by   subsequent   calls   to    wait_response/3,    check_response/3,    and
              receive_response/3. However, without deleting handled associations, the above calls
              will not be able to detect when there are no more outstanding requests  to  handle,
              so  you will have to keep track of this some other way than relying on a no_request
              return. Note that if you pass a collection only containing associations of  already
              handled  or  abandoned  requests  to  wait_response/3, it will always block until a
              timeout determined by WaitTime is triggered and then return no_reply.

CALLBACK FUNCTIONS

       The following functions are to be exported from a gen_statem callback module.

EXPORTS

       Module:callback_mode() -> CallbackMode

              Types:

                  CallbackMode = callback_mode() | [ callback_mode() | state_enter() ]

              This function is called by a gen_statem when it needs to find out the callback mode
              of  the  callback module. The value is cached by gen_statem for efficiency reasons,
              so this function is only called once after server start,  after  code  change,  and
              after  changing  the  callback  module,  but before the first state callback in the
              current callback module's code version is called. More occasions may  be  added  in
              future versions of gen_statem.

              Server  start  happens  either when Module:init/1 returns or when enter_loop/4-6 is
              called. Code change happens when Module:code_change/4  returns.  A  change  of  the
              callback  module  happens  when  a  state  callback  returns  any  of  the  actions
              change_callback_module, push_callback_module or pop_callback_module.

              The  CallbackMode  is  either   just   callback_mode()   or   a   list   containing
              callback_mode() and possibly the atom state_enter.

          Note:
              If  this  function's  body  does  not  return an inline constant value the callback
              module is doing something strange.

       Module:code_change(OldVsn, OldState, OldData, Extra) -> Result

              Types:

                 OldVsn = Vsn | {down,Vsn}
                  Vsn = term()
                 OldState = NewState = term()
                 Extra = term()
                 Result = {ok,NewState,NewData} | Reason
                  OldState = NewState = state()
                  OldData = NewData = data()
                 Reason = term()

          Note:
              This callback is optional, so callback modules need not export  it.  If  a  release
              upgrade/downgrade  with  Change  = {advanced,Extra} specified in the .appup file is
              made when code_change/4 is not implemented the process will crash with exit  reason
              undef.

              This  function  is  called  by a gen_statem when it is to update its internal state
              during   a   release   upgrade/downgrade,   that   is,   when    the    instruction
              {update,Module,Change,...},  where  Change  = {advanced,Extra}, is specified in the
              appup file. For more information, see OTP Design Principles.

              For an upgrade, OldVsn is Vsn, and for a downgrade, OldVsn is  {down,Vsn}.  Vsn  is
              defined  by  the vsn attribute(s) of the old version of the callback module Module.
              If no such attribute is defined, the version is the checksum of the Beam file.

              OldState and OldData is the internal state of the gen_statem.

              Extra is passed "as is" from the {advanced,Extra} part of the update instruction.

              If  successful,  the  function  must  return  the  updated  internal  state  in  an
              {ok,NewState,NewData} tuple.

              If  the function returns a failure Reason, the ongoing upgrade fails and rolls back
              to the old release. Note that Reason cannot be an {ok,_,_} tuple since that will be
              regarded  as  a {ok,NewState,NewData} tuple, and that a tuple matching {ok,_} is an
              also invalid failure Reason. It is recommended to use an atom as  Reason  since  it
              will be wrapped in an {error,Reason} tuple.

              Also  note  when  upgrading  a  gen_statem,  this  function  and hence the Change =
              {advanced,Extra} parameter in the appup file is  not  only  needed  to  update  the
              internal  state or to act on the Extra argument. It is also needed if an upgrade or
              downgrade should change callback mode, or else the callback  mode  after  the  code
              change will not be honoured, most probably causing a server crash.

              If    the   server   changes   callback   module   using   any   of   the   actions
              change_callback_module, push_callback_module or pop_callback_module, be aware  that
              it is always the current callback module that will get this callback call. That the
              current callback module handles the current state and  data  update  should  be  no
              surprise, but it must be able to handle even parts of the state and data that it is
              not familiar with, somehow.

              In the supervisor  child  specification  there  is  a  list  of  modules  which  is
              recommended  to  contain  only  the callback module. For a gen_statem with multiple
              callback modules there is no real need to list all of them,  it  may  not  even  be
              possible since the list could change after code upgrade. If this list would contain
              only the start callback module, as recommended, what is  important  is  to  upgrade
              that  module  whenever  a  synchronized  code replacement is done. Then the release
              handler concludes that an upgrade that upgrades that module needs to suspend,  code
              change,  and  resume any server whose child specification declares that it is using
              that  module.   And   again;   the   current   callback   module   will   get   the
              Module:code_change/4 call.

       Module:init(Args) -> Result(StateType)

              Types:

                 Args = term()
                  Result(StateType) = init_result(StateType)

              Whenever  a  gen_statem  is  started  using  start_link/3,4,  start_monitor/3,4, or
              start/3,4,  this  function  is  called  by  the  new  process  to  initialize   the
              implementation state and server data.

              Args is the Args argument provided to that start function.

          Note:
              Note  that  if  the gen_statem is started through proc_lib and enter_loop/4-6, this
              callback will never be called. Since this callback is not optional it can  in  that
              case be implemented as:

              -spec init(_) -> no_return().
              init(Args) -> erlang:error(not_implemented, [Args]).

       Module:format_status(Status) -> NewStatus

              Types:

                 Status = format_status()
                 NewStatus = format_status()

          Note:
              This  callback  is  optional,  so a callback module does not need to export it. The
              gen_statem module provides a default implementation of this function  that  returns
              {State,Data}.

              If  this  callback  is  exported  but  fails,  to hide possibly sensitive data, the
              default function will instead return {State,Info}, where Info says nothing but  the
              fact that format_status/2 has crashed.

              This function is called by a gen_statem process when any of the following apply:

                * sys:get_status/1,2 is invoked to get the gen_statem status.

                * The gen_statem process terminates abnormally and logs an error.

              This  function  is  useful  for  changing the form and appearance of the gen_statem
              status for these cases. A callback module wishing to change the  sys:get_status/1,2
              return  value  and  how  its  status  appears  in termination error logs exports an
              instance of format_status/1, which will get a map Status that describes the current
              states of the gen_statem, and shall return a map NewStatus containing the same keys
              as the input map, but it may transform some values.

              One  use  case  for  this  function  is  to  return   compact   alternative   state
              representations  to avoid having large state terms printed in log files. Another is
              to hide sensitive data from being written to the error log.

              Example:

              format_status(Status) ->
                maps:map(
                  fun(state,State) ->
                          maps:remove(private_key, State);
                     (message,{password, _Pass}) ->
                          {password, removed};
                     (_,Value) ->
                          Value
                  end, Status).

       Module:format_status(Opt, [PDict,State,Data]) -> Status

              Types:

                 Opt = normal | terminate
                 PDict = [{Key, Value}]
                  State = state()
                  Data = data()
                 Key = term()
                 Value = term()
                 Status = term()

          Warning:
              This callback is deprecated, in new code use  format_status/1. If a format_status/1
              callback exists, then this function will never be called.

          Note:
              This  callback  is  optional,  so a callback module does not need to export it. The
              gen_statem module provides a default implementation of this function  that  returns
              {State,Data}.

              If  this  callback  is  exported  but  fails,  to hide possibly sensitive data, the
              default function will instead return {State,Info}, where Info says nothing but  the
              fact that format_status/2 has crashed.

              This function is called by a gen_statem process when any of the following apply:

                *
                   One  of sys:get_status/1,2 is invoked to get the gen_statem status. Opt is set
                  to the atom normal for this case.

                *
                   The gen_statem terminates abnormally and logs an error. Opt is set to the atom
                  terminate for this case.

              This  function  is  useful  for  changing the form and appearance of the gen_statem
              status for these cases. A callback module wishing to change the  sys:get_status/1,2
              return  value  and  how  its  status  appears  in termination error logs exports an
              instance of format_status/2, which returns a term describing the current status  of
              the gen_statem.

              PDict is the current value of the process dictionary of the gen_statem.

              State is the internal state of the gen_statem.

              Data is the internal server data of the gen_statem.

              The  function  is to return Status, a term that contains the appropriate details of
              the current state and status of the gen_statem. There are no  restrictions  on  the
              form Status can take, but for the sys:get_status/1,2 case (when Opt is normal), the
              recommended form for the Status value is [{data, [{"State",  Term}]}],  where  Term
              provides relevant details of the gen_statem state. Following this recommendation is
              not required, but it makes the callback module status consistent with the  rest  of
              the sys:get_status/1,2 return value.

              One use for this function is to return compact alternative state representations to
              avoid having large state terms printed  in  log  files.  Another  use  is  to  hide
              sensitive data from being written to the error log.

       Module:StateName(enter, OldState, Data) -> StateEnterResult(StateName)
       Module:StateName(EventType, EventContent, Data) -> StateFunctionResult
       Module:handle_event(enter, OldState, State, Data) -> StateEnterResult(State)
       Module:handle_event(EventType, EventContent, State, Data) -> HandleEventResult

              Types:

                  EventType = event_type()
                 EventContent = term()
                  State = state()
                  Data = NewData = data()
                  StateEnterResult(StateName) = state_enter_result(StateName)
                  StateFunctionResult = event_handler_result(state_name())
                  StateEnterResult(State) = state_enter_result(State)
                  HandleEventResult = event_handler_result(state())

              Whenever a gen_statem receives an event from call/2, cast/2, or as a normal process
              message, one of these functions is called. If  callback  mode  is  state_functions,
              Module:StateName/3    is    called,    and    if   it   is   handle_event_function,
              Module:handle_event/4 is called.

              If EventType is {call,From}, the caller waits for a reply. The reply  can  be  sent
              from  this or from any other state callback by returning with {reply,From,Reply} in
              Actions, in Replies, or by calling reply(From, Reply).

              If this function returns with a next state that does not match equal (=/=)  to  the
              current state, all postponed events are retried in the next state.

              The  only  difference between StateFunctionResult and HandleEventResult is that for
              StateFunctionResult the next state must be an atom, but for HandleEventResult there
              is no restriction on the next state.

              For  options  that  can  be  set  and  actions that can be done by gen_statem after
              returning from this function, see action().

              When the gen_statem runs with state enter calls, these functions  are  also  called
              with arguments (enter, OldState, ...) during every state change. In this case there
              are some restrictions on the actions  that  may  be  returned:  postpone()  is  not
              allowed  since a state enter call is not an event so there is no event to postpone,
              and {next_event,_,_} is not allowed since using state enter calls should not affect
              how  events  are  consumed  and  produced. You may also not change states from this
              call. Should you return {next_state,NextState, ...} with NextState  =/=  State  the
              gen_statem crashes. Note that it is actually allowed to use {repeat_state, NewData,
              ...} although it makes little sense since you immediately will be called again with
              a  new  state  enter  call  making  this just a weird way of looping, and there are
              better ways to loop in Erlang. If you do not update  NewData  and  have  some  loop
              termination    condition,   or   if   you   use   {repeat_state_and_data,   _}   or
              repeat_state_and_data  you  have  an  infinite  loop!  You  are  advised   to   use
              {keep_state,...},  {keep_state_and_data,_}  or  keep_state_and_data  since changing
              states from a state enter call is not possible anyway.

              Note the fact that you can use throw to return the result, which can be useful. For
              example  to  bail out with throw(keep_state_and_data) from deep within complex code
              that cannot return {next_state,State,Data} because State or Data is  no  longer  in
              scope.

       Module:terminate(Reason, State, Data) -> Ignored

              Types:

                 Reason = normal | shutdown | {shutdown,term()} | term()
                 State = state()
                 Data = data()
                 Ignored = term()

          Note:
              This  callback  is optional, so callback modules need not export it. The gen_statem
              module provides a default implementation without cleanup.

              This function is called by a gen_statem when it is about to terminate. It is to  be
              the  opposite  of  Module:init/1 and do any necessary cleaning up. When it returns,
              the gen_statem terminates with Reason. The return value is ignored.

              Reason is a term denoting the stop reason and State is the internal  state  of  the
              gen_statem.

              Reason  depends  on  why  the  gen_statem  is terminating. If it is because another
              callback function has returned, a stop tuple {stop,Reason} in Actions,  Reason  has
              the  value  specified  in  that tuple. If it is because of a failure, Reason is the
              error reason.

              If the gen_statem is part of a supervision tree and is ordered by its supervisor to
              terminate,  this  function  is  called with Reason = shutdown if both the following
              conditions apply:

                * The gen_statem has been set to trap exit signals.

                * The shutdown strategy as defined in the supervisor's child specification is  an
                  integer time-out value, not brutal_kill.

              Even  if  the gen_statem is not part of a supervision tree, this function is called
              if it receives an 'EXIT' message from its parent. Reason is  the  same  as  in  the
              'EXIT' message.

              Otherwise, the gen_statem is immediately terminated.

              Notice  that  for  any  other reason than normal, shutdown, or {shutdown,Term}, the
              gen_statem is assumed to terminate because of an  error  and  an  error  report  is
              issued using logger(3erl).

              When  the  gen_statem process exits, an exit signal with the same reason is sent to
              linked processes and ports.

SEE ALSO

       gen_event(3erl),  gen_fsm(3erl),   gen_server(3erl),   proc_lib(3erl),   supervisor(3erl),
       sys(3erl).