Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
gen_statem(3)		   Erlang Module Definition		 gen_statem(3)

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 be-
       haviour remains in OTP "as is".

   Note:
       If you are new to gen_statem and	want an	overview of concepts and oper-
       ation 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	gener-
       ated 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 ac-
	   tions change_callback_module,  push_callback_module	and  pop_call-
	   back_module,	was added.

       gen_statem has got the same features that gen_fsm had and adds some re-
       ally 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  be-
       tween 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	 call-
       back 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	 acci-
       dentally	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 exe-
       cute   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 en-
       gine 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 cor-
       responds	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	incom-
       ing 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 han-
       dling 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  mod-
       ule 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 spec-
       ified gen_statem	does not exist or if bad arguments are specified.

       The gen_statem process can go  into  hibernation;  see  proc_lib:hiber-
       nate/3. It is done when a state callback	or Module:init/1 specifies hi-
       bernate in the returned Actions list. This feature can be useful	to re-
       claim 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  sig-
       nals.

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() =
	   {global, GlobalName :: term()} |
	   {via, RegMod	:: module(), Name :: term()} |
	   {local, atom()}

	      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  reg-
		  istry.  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,Global-
		  Name}	is the same as {global,GlobalName}.

       start_opt() =
	   {timeout, Time :: timeout()}	|
	   {spawn_opt, [proc_lib:start_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	hiber-
		  nation automatically (by calling proc_lib:hibernate/3).

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

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

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

       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 post-
	      poned 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	possi-
	      ble  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	inter-
	      nal.

	      internal events can only be generated by the state  machine  it-
	      self 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_re-
	      quest/2.	For  calls,  the event contains	whom to	reply to. Type
	      cast originates from the API function cast/2. Type  info	origi-
	      nates 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.

       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 Mod-
	      ule: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 Mod-
		  ule: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 us-
	      ing 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 pre-
	      vious  state callback returned and before	any event is delivered
	      to the new  state	 callback.  See	 Module:StateName/3  and  Mod-
	      ule:handle_event/4.  Such	 a call	can be repeated	by returning a
	      repeat_state or repeat_state_and_data tuple from the state call-
	      back.

	      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  re-
	      garded  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  se-
	      quence 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 argu-
		  ments	(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  en-
		  queued  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 transi-
		  tion option of this type belongs to the new state, that  is;
		  a state_timeout() applies to the state the state machine en-
		  ters.

		* If there are enqueued	events the state callback for the pos-
		  sibly	 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 call-
		  back 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:hiber-
	      nate/3  before  going  into  receive  to wait for	a new external
	      event.

	  Note:
	      If there are enqueued events to process when hibrnation  is  re-
	      quested,	this is	optimized by not hibernating but instead call-
	      ing erlang:garbage_collect/0 to simulate that the	gen_statem en-
	      tered  hibernation  and  immediately got awakened	by an enqueued
	      event.

       event_timeout() = timeout() | integer()

	      Starts a timer set by enter_action() timeout. When the timer ex-
	      pires  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 sup-
	      ported.

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

	      If  Time is infinity, no timer is	started, as it never would ex-
	      pire 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 pro-
	      cessed before any	not yet	received external event, but after al-
	      ready 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	neces-
	      sarily be	supported.

	      If Time is infinity, no timer is started,	as it never would  ex-
	      pire 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  pro-
	      cessed 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	neces-
	      sarily be	supported.

	      If  Time is infinity, no timer is	started, as it never would ex-
	      pire 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 pro-
	      cessed 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 :: term()} |
	   {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 Mod-
	      ule: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 ex-
	      ample, the last postpone() overrides any previous	postpone()  in
	      the list.

		postpone:
		  Sets the transition_option() postpone() for this state tran-
		  sition. This action  is  ignored  when  returned  from  Mod-
		  ule: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	inser-
		  tion 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 re-
		  liably distinguish an	event inserted this way	from  any  ex-
		  ternal 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 tran-
		  sition 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,   NewMod-
		  ule:code_change/4,  NewModule:format_status/2	 and   NewMod-
		  ule: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,  NewMod-
		  ule} 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 en-
	      ter_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 :: term()} |
	   {timeout,
	    Time :: event_timeout(),
	    EventContent :: term(),
	    Options :: timeout_option()	| [timeout_option()]} |
	   {{timeout, Name :: term()},
	    Time :: generic_timeout(),
	    EventContent :: term()} |
	   {{timeout, Name :: term()},
	    Time :: generic_timeout(),
	    EventContent :: term(),
	    Options :: timeout_option()	| [timeout_option()]} |
	   {state_timeout,
	    Time :: state_timeout(),
	    EventContent :: term()} |
	   {state_timeout,
	    Time :: state_timeout(),
	    EventContent :: term(),
	    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 en-
	      ter_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 :: term()} |
	   {{timeout, Name :: term()}, update, EventContent :: term()} |
	   {state_timeout, update, EventContent	:: term()}

	      Updates  a  time-out  with  a new	EventContent. See  timeout_ac-
	      tion()  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 en-
	      ter_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  Ac-
		  tions.

       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 ex-
		  ecutes 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 en-
		  ter 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() = term()

	      A	request	handle,	see send_request/2 for details.

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 {re-
	      ply,From,Reply} as one action(), and that	Reply becomes the  re-
	      turn 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	speci-
	      fied 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 func-
	      tion 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_time-
	      out,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  be-
	      fore or during this function call.

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

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

       check_response(Msg :: term(), RequestId :: request_id())	->
			 {reply, Reply :: term()} |
			 no_reply |
			 {error, {term(), server_ref()}}

	      This function is used to check if	a previously received message,
	      for  example  by	receive	or handle_info/2, is a result of a re-
	      quest made with send_request/2. If Msg is	a reply	to the	handle
	      RequestId	the result of the request is returned in Reply.	Other-
	      wise returns no_reply and	no cleanup is done, and	thus the func-
	      tion shall be invoked repeatedly until a reply is	returned.

	      The  return  value  Reply	is generated when a state callback re-
	      turns 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.

       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	anony-
	      mous 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  ex-
	      cept 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_Ac-
	      tions 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  pro-
	      cedure 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|_moni-
	      tor]/4.  However,	 the  server_name() name must have been	regis-
	      tered 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(RequestId :: request_id()) ->
			   {reply, Reply :: term()} |
			   {error, {term(), server_ref()}}

       receive_response(RequestId :: request_id(), Timeout :: timeout()) ->
			   {reply, Reply :: term()} |
			   timeout |
			   {error, {term(), server_ref()}}

	      This function is used to receive for a reply of a	 request  made
	      with  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  is an integer greater then or equal to zero that	speci-
	      fies how many milliseconds to wait for an	reply, or the atom in-
	      finity  to  wait indefinitely. Defaults to infinity. If no reply
	      is received within the  specified	 time,	the  function  returns
	      timeout.	Assuming that the server executes on a node supporting
	      aliases (introduced in OTP 24) no	response will be received  af-
	      ter  a  timeout. Otherwise, a garbage response might be received
	      at a later time.

	      The return value Reply is	generated when a  state	 callback  re-
	      turns  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() and receive_response() is
	      that receive_response() abandons the request at timeout so  that
	      a	 potential  future  response is	ignored, while wait_response()
	      does not.

       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 out-
	      put.

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

	      Sends a request to the gen_statem	ServerRef and returns a	handle
	      RequestId.

	      The return value RequestId shall later be	used with  receive_re-
	      sponse/1,2,  wait_response/1,2, or check_response/2 to fetch the
	      actual result of the request.

	      The      call	  gen_statem:wait_response(gen_statem:send_re-
	      quest(ServerRef,Request),	 Timeout) can be seen as equivalent to
	      gen_statem:call(Server,Request,Timeout), ignoring	the error han-
	      dling.

	      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  {re-
	      ply,From,Reply}  as one action(),	and that Reply becomes the re-
	      turn  value  of  receive_response/1,2,   wait_response/1,2,   or
	      check_response/2 function.

       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 Mod-
	      ule: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  Hi-
		  bernateAfterTimeout  milliseconds  and  if no	message	is re-
		  ceived, 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	 func-
	      tion 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 {er-
	      ror,Reason}. If Module:init/1 returns {stop,Reason}  or  ignore,
	      the  process is terminated and this function returns {error,Rea-
	      son} or ignore, respectively. An exit signal with	the same  Rea-
	      son (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  Rea-
	      son  and	waits  for  it to terminate. The gen_statem calls Mod-
	      ule:terminate/3 before exiting.

	      This function returns ok if the server terminates	with  the  ex-
	      pected reason. Any other reason than normal, shutdown, or	{shut-
	      down,Term} causes	an error report	 to  be	 issued	 through  log-
	      ger(3).  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,	a timeout exception is
	      raised.

	      If the process does not exist, a noproc exception	is raised.

       wait_response(RequestId :: request_id())	->
			{reply,	Reply :: term()} |
			{error,	{term(), server_ref()}}

       wait_response(RequestId :: request_id(),	Timeout	:: timeout()) ->
			{reply,	Reply :: term()} |
			timeout	|
			{error,	{term(), server_ref()}}

	      This function is used to wait for	a reply	of a request made with
	      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 is an integer greater then or equal to zero that	speci-
	      fies how many milliseconds to wait for an	reply, or the atom in-
	      finity to	wait indefinitely. Defaults to infinity. If  no	 reply
	      is  received  within  the	 specified  time, the function returns
	      timeout and no cleanup is	done, and thus the function can	be in-
	      voked repeatedly until a reply is	returned.

	      The  return  value  Reply	is generated when a state callback re-
	      turns 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()	and wait_response() is
	      that  receive_response() abandons	the request at timeout so that
	      a	potential future response is  ignored,	while  wait_response()
	      does not.

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  af-
	      ter  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  Mod-
	      ule:code_change/4	returns. A change of the callback module  hap-
	      pens   when   a  state  callback	returns	 any  of  the  actions
	      change_callback_module,	push_callback_module   or    pop_call-
	      back_module.

	      The  CallbackMode	 is either just	callback_mode()	or a list con-
	      taining 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,Ex-
	      tra}  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 =  {ad-
	      vanced,Extra}, is	specified in the appup file. For more informa-
	      tion, 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,New-
	      State,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_call-
	      back_module, be aware that it is	always	the  current  callback
	      module  that will	get this callback call.	That the current call-
	      back 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  en-
	      ter_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(Opt, [PDict,State,Data]) ->	Status

	      Types:

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

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

	      If this callback is exported but fails, to hide possibly	sensi-
	      tive   data,   the   default   function	will   instead	return
	      {State,Info}, where Info says nothing but	 the  fact  that  for-
	      mat_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 for-
	      mat_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  ap-
	      propriate	 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)  ->	 StateEnterRe-
       sult(State)
       Module:handle_event(EventType,  EventContent,  State,  Data)  ->	  Han-
       dleEventResult

	      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:han-
	      dle_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 re-
	      tried in the next	state.

	      The only difference between StateFunctionResult and  HandleEven-
	      tResult  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 ev-
	      ery 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  pro-
	      duced. 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 {re-
	      peat_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	  {re-
	      peat_state_and_data, _} or repeat_state_and_data you have	an in-
	      finite  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 ter-
	      minate.  It  is  to  be the opposite of Module:init/1 and	do any
	      necessary	cleaning up. When it returns,  the  gen_statem	termi-
	      nates with Reason. The return value is ignored.

	      Reason  is  a term denoting the stop reason and State is the in-
	      ternal 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 rea-
	      son.

	      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(3).

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

SEE ALSO
       gen_event(3), gen_fsm(3),  gen_server(3),  proc_lib(3),	supervisor(3),
       sys(3).

Ericsson AB			  stdlib 3.17			 gen_statem(3)

NAME | DESCRIPTION | EXAMPLE | DATA TYPES | EXPORTS | CALLBACK FUNCTIONS | EXPORTS | SEE ALSO

Want to link to this manual page? Use this URL:
<https://www.freebsd.org/cgi/man.cgi?query=gen_statem&sektion=3&manpath=FreeBSD+13.1-RELEASE+and+Ports>

home | help