diff options
Diffstat (limited to 'lib/stdlib/doc/src/gen_statem.xml')
-rw-r--r-- | lib/stdlib/doc/src/gen_statem.xml | 2306 |
1 files changed, 2306 insertions, 0 deletions
diff --git a/lib/stdlib/doc/src/gen_statem.xml b/lib/stdlib/doc/src/gen_statem.xml new file mode 100644 index 0000000000..a808d3af55 --- /dev/null +++ b/lib/stdlib/doc/src/gen_statem.xml @@ -0,0 +1,2306 @@ +<?xml version="1.0" encoding="utf-8" ?> +<!DOCTYPE erlref SYSTEM "erlref.dtd"> + +<erlref> + <header> + <copyright> + <year>2016</year><year>2018</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + </legalnotice> + + <title>gen_statem</title> + <prepared></prepared> + <docno></docno> + <date></date> + <rev></rev> + </header> + <module>gen_statem</module> + <modulesummary>Generic state machine behavior.</modulesummary> + <description> + <p> + <c>gen_statem</c> provides a generic state machine behaviour + and replaces its predecessor + <seealso marker="gen_fsm"><c>gen_fsm</c></seealso> + since Erlang/OTP 20.0. + </p> + <p> + This reference manual describes types generated from the types + in the <c>gen_statem</c> source code, so they are correct. + However, the generated descriptions also reflect the type hiearchy, + which makes them kind of hard to read. + </p> + <p> + To get an overview of the concepts and operation of <c>gen_statem</c>, + do read the + <seealso marker="doc/design_principles:statem"> + <c>gen_statem</c> Behaviour + </seealso> + in + <seealso marker="doc/design_principles:users_guide"> + OTP Design Principles + </seealso> + which frequently links back to this reference manual to avoid + containing detailed facts that may rot by age. + </p> + <note> + <p> + This behavior appeared in Erlang/OTP 19.0. + In OTP 19.1 a backwards incompatible change of + the return tuple from + <seealso marker="#Module:init/1"><c>Module:init/1</c></seealso> + was made and the mandatory callback function + <seealso marker="#Module:callback_mode/0"> + <c>Module:callback_mode/0</c> + </seealso> + was introduced. In OTP 20.0 the + <seealso marker="#type-generic_timeout"><c>generic timeouts</c></seealso> + were added. + </p> + </note> + <p> + <c>gen_statem</c> has got the same features that + <seealso marker="gen_fsm"><c>gen_fsm</c></seealso> + had and adds some really useful: + </p> + <list type="bulleted"> + <item>Co-located state code</item> + <item>Arbitrary term state</item> + <item>Event postponing</item> + <item>Self-generated events</item> + <item>State time-out</item> + <item>Multiple generic named time-outs</item> + <item>Absolute time-out time</item> + <item>Automatic state enter calls</item> + <item> + Reply from other state than the request, <c>sys</c> traceable + </item> + <item>Multiple <c>sys</c> traceable replies</item> + </list> + + + <p> + Two + <seealso marker="#type-callback_mode"><em>callback modes</em></seealso> + are supported: + </p> + <list type="bulleted"> + <item> + <p>One for finite-state machines + (<seealso marker="gen_fsm"><c>gen_fsm</c></seealso> like), + which requires the state to be an atom and uses that state as + the name of the current callback function + </p> + </item> + <item> + <p>One without restriction on the state data type + that uses one callback function for all states + </p> + </item> + </list> + <p> + The callback model(s) for <c>gen_statem</c> differs from + the one for <seealso marker="gen_fsm"><c>gen_fsm</c></seealso>, + but it is still fairly easy to + <seealso marker="gen_fsm#Migration to gen_statem"> + rewrite from + </seealso> <c>gen_fsm</c> to <c>gen_statem</c>. + </p> + <p> + A generic state machine process (<c>gen_statem</c>) 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 + <seealso marker="doc/design_principles:statem">OTP Design Principles</seealso>. + </p> + <p> + A <c>gen_statem</c> 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:</p> + <pre> +gen_statem module Callback module +----------------- --------------- +gen_statem:start +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 +erlang:send +erlang:'!' -----> Module:StateName/3 + Module:handle_event/4 + +- -----> Module:terminate/3 + +- -----> Module:code_change/4</pre> + <p> + Events are of different + <seealso marker="#type-event_type">types</seealso>, + so the callback functions can know the origin of an event + and how to respond. + </p> + <p> + If a callback function fails or returns a bad value, + the <c>gen_statem</c> terminates, unless otherwise stated. + However, an exception of class + <seealso marker="erts:erlang#throw/1"><c>throw</c></seealso> + is not regarded as an error but as a valid return + from all callback functions. + </p> + <marker id="state callback"/> + <p> + The "<em>state callback</em>" for a specific + <seealso marker="#type-state">state</seealso> + in a <c>gen_statem</c> is the callback function that is called + for all events in this state. It is selected depending on which + <seealso marker="#type-callback_mode"><em>callback mode</em></seealso> + that the callback module defines with the callback function + <seealso marker="#Module:callback_mode/0"><c>Module:callback_mode/0</c></seealso>. + </p> + <p> + When the + <seealso marker="#type-callback_mode"><em>callback mode</em></seealso> + is <c>state_functions</c>, the state must be an atom and + is used as the state callback name; see + <seealso marker="#Module:StateName/3"><c>Module:StateName/3</c></seealso>. + This co-locates all code for a specific state + in one function as the <c>gen_statem</c> engine + branches depending on state name. + Note the fact that the callback function + <seealso marker="#Module:terminate/3"><c>Module:terminate/3</c></seealso> + makes the state name <c>terminate</c> unusable in this mode. + </p> + <p> + When the + <seealso marker="#type-callback_mode"><em>callback mode</em></seealso> + is <c>handle_event_function</c>, the state can be any term + and the state callback name is + <seealso marker="#Module:handle_event/4"><c>Module:handle_event/4</c></seealso>. + 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. + </p> + <p> + The <c>gen_statem</c> enqueues incoming events in order of arrival + and presents these to the + <seealso marker="#state callback">state callback</seealso> + in that order. The state callback can postpone an event + so it is not retried in the current state. + After a state change the queue restarts with the postponed events. + </p> + <p> + The <c>gen_statem</c> 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. + </p> + <p> + The <seealso marker="#state callback">state callback</seealso> + can insert events using the + <seealso marker="#type-action"><c>action()</c></seealso> + <c>next_event</c> + and such an event is inserted as the next to present + to the state callback. That is, as if it is + the oldest incoming event. A dedicated + <seealso marker="#type-event_type"><c>event_type()</c></seealso> + <c>internal</c> can be used for such events making them impossible + to mistake for external events. + </p> + <p> + Inserting an event replaces the trick of calling your own + state handling functions that you often would have to + resort to in, for example, + <seealso marker="gen_fsm"><c>gen_fsm</c></seealso> + to force processing an inserted event before others. + </p> + <p> + The <c>gen_statem</c> engine can automatically + make a specialized call to the + <seealso marker="#state callback">state callback</seealso> + whenever a new state is entered; see + <seealso marker="#type-state_enter"><c>state_enter()</c></seealso>. + This is for writing code common to all state entries. + Another way to do it is to 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. + </p> + <note> + <p>If you in <c>gen_statem</c>, for example, postpone + an event in one state and then call another state callback + of yours, you have not changed states and hence the postponed event + is not retried, which is logical but can be confusing. + </p> + </note> + <p> + For the details of a state transition, see type + <seealso marker="#type-transition_option"><c>transition_option()</c></seealso>. + </p> + <p> + A <c>gen_statem</c> handles system messages as described in + <seealso marker="sys"><c>sys</c></seealso>. + The <c>sys</c> module can be used for debugging a <c>gen_statem</c>. + </p> + <p> + Notice that a <c>gen_statem</c> does not trap exit signals + automatically, this must be explicitly initiated in + the callback module (by calling + <seealso marker="erts:erlang#process_flag/2"><c>process_flag(trap_exit, true)</c></seealso>. + </p> + <p> + Unless otherwise stated, all functions in this module fail if + the specified <c>gen_statem</c> does not exist or + if bad arguments are specified. + </p> + <p> + The <c>gen_statem</c> process can go into hibernation; see + <seealso marker="proc_lib#hibernate/3"><c>proc_lib:hibernate/3</c></seealso>. + It is done when a + <seealso marker="#state callback">state callback</seealso> or + <seealso marker="#Module:init/1"><c>Module:init/1</c></seealso> + specifies <c>hibernate</c> in the returned + <seealso marker="#type-action"><c>Actions</c></seealso> + 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 + <seealso marker="erts:erlang#hibernate/3"><c>erlang:hibernate/3</c></seealso>. + </p> + <p> + There is also a server start option + <seealso marker="#type-hibernate_after_opt"> + <c>{hibernate_after, Timeout}</c> + </seealso> + for + <seealso marker="#start/3"><c>start/3,4</c></seealso> or + <seealso marker="#start_link/3"><c>start_link/3,4</c></seealso> + that may be used to automatically hibernate the server. + </p> + </description> + + <section> + <title>Example</title> + <p> + The following example shows a simple pushbutton model + for a toggling pushbutton implemented with + <seealso marker="#type-callback_mode"><em>callback mode</em></seealso> + <c>state_functions</c>. + 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. + </p> + <p>The following is the complete callback module file + <c>pushbutton.erl</c>:</p> + <code type="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}. + </code> + <p>The following is a shell session when running it:</p> + <pre> +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) + </pre> + <p> + To compare styles, here follows the same example using + <seealso marker="#type-callback_mode"><em>callback mode</em></seealso> + <c>handle_event_function</c>, or rather the code to replace + after function <c>init/1</c> of the <c>pushbutton.erl</c> + example file above: + </p> + <code type="erl"> +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}. + </code> + </section> + + <datatypes> + <datatype> + <name name="server_name"/> + <desc> + <p> + Name specification to use when starting + a <c>gen_statem</c> server. See + <seealso marker="#start_link/3"><c>start_link/3</c></seealso> + and + <seealso marker="#type-server_ref"><c>server_ref()</c></seealso> + below. + </p> + </desc> + </datatype> + <datatype> + <name name="server_ref"/> + <desc> + <p> + Server specification to use when addressing + a <c>gen_statem</c> server. + See <seealso marker="#call/2"><c>call/2</c></seealso> and + <seealso marker="#type-server_name"><c>server_name()</c></seealso> + above. + </p> + <p>It can be:</p> + <taglist> + <tag><c>pid() | LocalName</c></tag> + <item> + <p> + The <c>gen_statem</c> is locally registered. + </p> + </item> + <tag><c>{Name,Node}</c></tag> + <item> + <p> + The <c>gen_statem</c> is locally registered + on another node. + </p> + </item> + <tag><c>{global,GlobalName}</c></tag> + <item> + <p> + The <c>gen_statem</c> is globally registered in + <seealso marker="kernel:global"><c>global</c></seealso>. + </p> + </item> + <tag><c>{via,RegMod,ViaName}</c></tag> + <item> + <p> + The <c>gen_statem</c> is registered in + an alternative process registry. + The registry callback module <c>RegMod</c> + is to export functions + <c>register_name/2</c>, <c>unregister_name/1</c>, + <c>whereis_name/1</c>, and <c>send/2</c>, + which are to behave like the corresponding functions in + <seealso marker="kernel:global"><c>global</c></seealso>. + Thus, <c>{via,global,GlobalName}</c> is the same as + <c>{global,GlobalName}</c>. + </p> + </item> + </taglist> + </desc> + </datatype> + <datatype> + <name name="debug_opt"/> + <desc> + <p> + Debug option that can be used when starting + a <c>gen_statem</c> server through, + <seealso marker="#enter_loop/4"><c>enter_loop/4-6</c></seealso>. + </p> + <p> + For every entry in <c><anno>Dbgs</anno></c>, + the corresponding function in + <seealso marker="sys"><c>sys</c></seealso> is called. + </p> + </desc> + </datatype> + <datatype> + <name name="hibernate_after_opt"/> + <desc> + <p> + hibernate_after option that can be used when starting + a <c>gen_statem</c> server through, + <seealso marker="#enter_loop/4"><c>enter_loop/4-6</c></seealso>. + </p> + <p>If option<seealso marker="#type-hibernate_after_opt"><c>{hibernate_after,HibernateAfterTimeout}</c></seealso> is present, the <c>gen_statem</c> + process awaits any message for <c>HibernateAfterTimeout</c> milliseconds and + if no message is received, the process goes into hibernation automatically + (by calling <seealso marker="proc_lib#hibernate/3"><c>proc_lib:hibernate/3</c></seealso>). + </p> + </desc> + </datatype> + <datatype> + <name name="start_opt"/> + <desc> + <p> + Options that can be used when starting + a <c>gen_statem</c> server through, for example, + <seealso marker="#start_link/3"><c>start_link/3</c></seealso>. + </p> + </desc> + </datatype> + <datatype> + <name name="start_ret"/> + <desc> + <p> + Return value from the start functions, for example, + <seealso marker="#start_link/3"><c>start_link/3</c></seealso>. + </p> + </desc> + </datatype> + <datatype> + <name name="from"/> + <desc> + <p> + Destination to use when replying through, for example, the + <seealso marker="#type-action"><c>action()</c></seealso> + <c>{reply,From,Reply}</c> + to a process that has called the <c>gen_statem</c> server using + <seealso marker="#call/2"><c>call/2</c></seealso>. + </p> + </desc> + </datatype> + <datatype> + <name name="state"/> + <desc> + <p> + If the + <seealso marker="#type-callback_mode"><em>callback mode</em></seealso> + is <c>handle_event_function</c>, + the state can be any term. + After a state change (<c>NextState =/= State</c>), + all postponed events are retried. + </p> + </desc> + </datatype> + <datatype> + <name name="state_name"/> + <desc> + <p> + If the + <seealso marker="#type-callback_mode"><em>callback mode</em></seealso> + is <c>state_functions</c>, + the state must be of this type. + After a state change (<c>NextState =/= State</c>), + all postponed events are retried. + </p> + </desc> + </datatype> + <datatype> + <name name="data"/> + <desc> + <p> + A term in which the state machine implementation + is to store any server data it needs. The difference between + this and the <seealso marker="#type-state"><c>state()</c></seealso> + 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. + </p> + </desc> + </datatype> + <datatype> + <name name="event_type"/> + <desc> + <p> + There are 3 categories of events: + <seealso marker="#type-external_event_type">external</seealso>, + <seealso marker="#type-timeout_event_type">timeout</seealso>, + and <c>internal</c>. + </p> + <p> + <c>internal</c> events can only be generated by the + state machine itself through the state transition action + <seealso marker="#type-action"><c>next_event</c></seealso>. + </p> + </desc> + </datatype> + <datatype> + <name name="external_event_type"/> + <desc> + <p> + External events are of 3 types: + <c>{call,<anno>From</anno>}</c>, <c>cast</c>, or <c>info</c>. + <seealso marker="#call/2">Calls</seealso> + (synchronous) and + <seealso marker="#cast/2">casts</seealso> + originate from the corresponding API functions. + For calls, the event contains whom to reply to. + Type <c>info</c> originates from regular process messages sent + to the <c>gen_statem</c>. + </p> + </desc> + </datatype> + <datatype> + <name name="timeout_event_type"/> + <desc> + <p> + There are 3 types of timeout events that the state machine + can generate for itself with the corresponding + <seealso marker="#type-timeout_action">timeout_action()</seealso>s. + </p> + </desc> + </datatype> + <datatype> + <name name="callback_mode_result"/> + <desc> + <p> + This is the return type from + <seealso marker="#Module:callback_mode/0"><c>Module:callback_mode/0</c></seealso> + and selects + <seealso marker="#type-callback_mode">callback mode</seealso> + and whether to do + <seealso marker="#type-state_enter">state enter calls</seealso>, + or not. + </p> + </desc> + </datatype> + <datatype> + <name name="callback_mode"/> + <desc> + <p> + The <em>callback mode</em> is selected when starting the + <c>gen_statem</c> and after code change + using the return value from + <seealso marker="#Module:callback_mode/0"><c>Module:callback_mode/0</c></seealso>. + </p> + <taglist> + <tag><c>state_functions</c></tag> + <item> + <p> + The state must be of type + <seealso marker="#type-state_name"><c>state_name()</c></seealso> + and one callback function per state, that is, + <seealso marker="#Module:StateName/3"><c>Module:StateName/3</c></seealso>, + is used. + </p> + </item> + <tag><c>handle_event_function</c></tag> + <item> + <p> + The state can be any term and the callback function + <seealso marker="#Module:handle_event/4"><c>Module:handle_event/4</c></seealso> + is used for all states. + </p> + </item> + </taglist> + </desc> + </datatype> + <datatype> + <name name="state_enter"/> + <desc> + <p> + Whether the state machine should use <em>state enter calls</em> + or not is selected when starting the <c>gen_statem</c> + and after code change using the return value from + <seealso marker="#Module:callback_mode/0"><c>Module:callback_mode/0</c></seealso>. + </p> + <p> + If + <seealso marker="#Module:callback_mode/0"><c>Module:callback_mode/0</c></seealso> + returns a list containing <c>state_enter</c>, + the <c>gen_statem</c> engine will, at every state change, + call the + <seealso marker="#state callback">state callback</seealso> + with arguments <c>(enter, OldState, Data)</c>. + 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 + <seealso marker="#Module:StateName/3"><c>Module:StateName/3</c></seealso> + and + <seealso marker="#Module:handle_event/4"><c>Module:handle_event/4</c></seealso>. + Such a call can be repeated by returning a + <seealso marker="#type-state_callback_result"> + <c>repeat_state</c> + </seealso> + or + <seealso marker="#type-state_callback_result"> + <c>repeat_state_and_data</c> + </seealso> + tuple from the state callback. + </p> + <p> + If + <seealso marker="#Module:callback_mode/0"><c>Module:callback_mode/0</c></seealso> + does not return such a list, no state enter calls are done. + </p> + <p> + If + <seealso marker="#Module:code_change/4"><c>Module:code_change/4</c></seealso> + should transform the state, + it is regarded as a state rename and not a state change, + which will not cause a state enter call. + </p> + <p> + Note that a state enter call <em>will</em> be done + right before entering the initial state even though this + formally is not a state change. + In this case <c>OldState</c> will be the same as <c>State</c>, + which can not happen for a subsequent state change, + but will happen when repeating the state enter call. + </p> + </desc> + </datatype> + <datatype> + <name name="transition_option"/> + <desc> + <p> + Transition options can be set by + <seealso marker="#type-action">actions</seealso> + and modify the state transition. + Here are the sequence of steps for a state transition: + </p> + <list type="ordered"> + <item> + <p> + If + <seealso marker="#type-state_enter"> + <em>state enter calls</em> + </seealso> + are used, and either: + the state changes, it is the initial state, + or one of the callback results + <seealso marker="#type-state_callback_result"> + <c>repeat_state</c> + </seealso> + or + <seealso marker="#type-state_callback_result"> + <c>repeat_state_and_data</c> + </seealso> + is used; the <c>gen_statem</c> calls + the new state callback with arguments + <seealso marker="#type-state_enter"><c>(enter, OldState, Data)</c></seealso>. + </p> + <p> + Any + <seealso marker="#type-enter_action">actions</seealso> + returned from this call are handled as if they were + appended to the actions + returned by the state callback that caused the state entry. + </p> + <p> + Should this state enter call return any of + the mentioned <c>repeat_*</c> callback results + it is repeated again, with the updated <c>Data</c>. + </p> + </item> + <item> + <p> + All + <seealso marker="#type-action">actions</seealso> + are processed in order of appearance. + </p> + </item> + <item> + <p> + If + <seealso marker="#type-postpone"><c>postpone()</c></seealso> + is <c>true</c>, + the current event is postponed. + </p> + </item> + <item> + <p> + If the state changes, the queue of incoming events + is reset to start with the oldest postponed. + </p> + </item> + <item> + <p> + All events stored with + <seealso marker="#type-action"><c>action()</c></seealso> + <c>next_event</c> + are inserted to be processed before previously queued events. + </p> + </item> + <item> + <p> + Time-out timers + <seealso marker="#type-event_timeout"><c>event_timeout()</c></seealso>, + <seealso marker="#type-generic_timeout"><c>generic_timeout()</c></seealso> + and + <seealso marker="#type-state_timeout"><c>state_timeout()</c></seealso> + 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. + </p> + <p> + Any event cancels an + <seealso marker="#type-event_timeout"><c>event_timeout()</c></seealso> + so a zero time event time-out is only generated + if the event queue is empty. + </p> + <p> + A state change cancels a + <seealso marker="#type-state_timeout"><c>state_timeout()</c></seealso> + and any new transition option of this type + belongs to the new state. + </p> + </item> + <item> + <p> + If there are enqueued events the + <seealso marker="#state callback">state callback</seealso> + for the possibly new state + is called with the oldest enqueued event, + and we start again from the top of this list. + </p> + </item> + <item> + <p> + Otherwise the <c>gen_statem</c> goes into <c>receive</c> + or hibernation + (if + <seealso marker="#type-hibernate"><c>hibernate()</c></seealso> + is <c>true</c>) + to wait for the next message. In hibernation the next + non-system event awakens the <c>gen_statem</c>, or rather + the next incoming message awakens the <c>gen_statem</c>, + but if it is a system event it goes right back into hibernation. + When a new message arrives the + <seealso marker="#state callback">state callback</seealso> + is called with the corresponding event, + and we start again from the top of this sequence. + </p> + </item> + </list> + </desc> + </datatype> + <datatype> + <name name="postpone"/> + <desc> + <p> + If <c>true</c>, postpones the current event and retries + it when the state changes + (<c>NextState =/= State</c>). + </p> + </desc> + </datatype> + <datatype> + <name name="hibernate"/> + <desc> + <p> + If <c>true</c>, hibernates the <c>gen_statem</c> + by calling + <seealso marker="proc_lib#hibernate/3"><c>proc_lib:hibernate/3</c></seealso> + before going into <c>receive</c> + to wait for a new external event. + </p> + <note> + <p> + If there are enqueued events to process + when hibrnation is requested, + this is optimized by not hibernating but instead calling + <seealso marker="erts:erlang#garbage_collect/0"> + <c>erlang:garbage_collect/0</c> + </seealso> + to simulate that the <c>gen_statem</c> entered hibernation + and immediately got awakened by an enqueued event. + </p> + </note> + </desc> + </datatype> + <datatype> + <name name="event_timeout"/> + <desc> + <p> + Starts a timer set by + <seealso marker="#type-enter_action"><c>enter_action()</c></seealso> + <c>timeout</c>. + When the timer expires an event of + <seealso marker="#type-event_type"><c>event_type()</c></seealso> + <c>timeout</c> will be generated. + See + <seealso marker="erts:erlang#start_timer/4"><c>erlang:start_timer/4</c></seealso> + for how <c>Time</c> and + <seealso marker="#type-timeout_option"><c>Options</c></seealso> + are interpreted. Future <c>erlang:start_timer/4</c> <c>Options</c> + will not necessarily be supported. + </p> + <p> + 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. + </p> + <p> + If <c>Time</c> is <c>infinity</c>, + no timer is started, as it never would expire anyway. + </p> + <p> + If <c>Time</c> is relative and <c>0</c> + 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. + </p> + <p> + Note that it is not possible nor needed to cancel this time-out, + as it is cancelled automatically by any other event. + </p> + </desc> + </datatype> + <datatype> + <name name="generic_timeout"/> + <desc> + <p> + Starts a timer set by + <seealso marker="#type-enter_action"><c>enter_action()</c></seealso> + <c>{timeout,Name}</c>. + When the timer expires an event of + <seealso marker="#type-event_type"><c>event_type()</c></seealso> + <c>{timeout,Name}</c> will be generated. + See + <seealso marker="erts:erlang#start_timer/4"><c>erlang:start_timer/4</c></seealso> + for how <c>Time</c> and + <seealso marker="#type-timeout_option"><c>Options</c></seealso> + are interpreted. Future <c>erlang:start_timer/4</c> <c>Options</c> + will not necessarily be supported. + </p> + <p> + If <c>Time</c> is <c>infinity</c>, + no timer is started, as it never would expire anyway. + </p> + <p> + If <c>Time</c> is relative and <c>0</c> + 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. + </p> + <p> + Setting a timer with the same <c>Name</c> 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 <c>infinity</c>. + </p> + </desc> + </datatype> + <datatype> + <name name="state_timeout"/> + <desc> + <p> + Starts a timer set by + <seealso marker="#type-enter_action"><c>enter_action()</c></seealso> + <c>state_timeout</c>. + When the timer expires an event of + <seealso marker="#type-event_type"><c>event_type()</c></seealso> + <c>state_timeout</c> will be generated. + See + <seealso marker="erts:erlang#start_timer/4"><c>erlang:start_timer/4</c></seealso> + for how <c>Time</c> and + <seealso marker="#type-timeout_option"><c>Options</c></seealso> + are interpreted. Future <c>erlang:start_timer/4</c> <c>Options</c> + will not necessarily be supported. + </p> + <p> + If <c>Time</c> is <c>infinity</c>, + no timer is started, as it never would expire anyway. + </p> + <p> + If <c>Time</c> is relative and <c>0</c> + 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. + </p> + <p> + 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 <c>infinity</c>. + </p> + </desc> + </datatype> + <datatype> + <name name="timeout_option"/> + <desc> + <p> + If <c>Abs</c> is <c>true</c> an absolute timer is started, + and if it is <c>false</c> a relative, which is the default. + See + <seealso marker="erts:erlang#start_timer/4"> + <c>erlang:start_timer/4</c> + </seealso> + for details. + </p> + <p> + </p> + </desc> + </datatype> + <datatype> + <name name="action"/> + <desc> + <p> + These state transition actions can be invoked by + returning them from the + <seealso marker="#state callback">state callback</seealso> + when it is called with an + <seealso marker="#type-event_type">event</seealso>, + from + <seealso marker="#Module:init/1"><c>Module:init/1</c></seealso> + or by giving them to + <seealso marker="#enter_loop/5"><c>enter_loop/5,6</c></seealso>. + </p> + <p> + Actions are executed in the containing list order. + </p> + <p> + Actions that set + <seealso marker="#type-transition_option"> + transition options + </seealso> + override any previous of the same type, + so the last in the containing list wins. + For example, the last + <seealso marker="#type-postpone"><c>postpone()</c></seealso> + overrides any previous <c>postpone()</c> in the list. + </p> + <taglist> + <tag><c>postpone</c></tag> + <item> + <p> + Sets the + <seealso marker="#type-transition_option"> + <c>transition_option()</c> + </seealso> + <seealso marker="#type-postpone"><c>postpone()</c></seealso> + for this state transition. + This action is ignored when returned from + <seealso marker="#Module:init/1"><c>Module:init/1</c></seealso> + or given to + <seealso marker="#enter_loop/5"><c>enter_loop/5,6</c></seealso>, + as there is no event to postpone in those cases. + </p> + </item> + <tag><c>next_event</c></tag> + <item> + <p> + This action does not set any + <seealso marker="#type-transition_option"> + <c>transition_option()</c> + </seealso> + but instead stores the specified <c><anno>EventType</anno></c> + and <c><anno>EventContent</anno></c> for insertion after all + actions have been executed. + </p> + <p> + 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 <c>next_event</c> in the containing + list becomes the first to process. + </p> + <p> + An event of type + <seealso marker="#type-event_type"><c>internal</c></seealso> + is to be used when you want to reliably distinguish + an event inserted this way from any external event. + </p> + </item> + </taglist> + </desc> + </datatype> + <datatype> + <name name="enter_action"/> + <desc> + <p> + These state transition actions can be invoked by + returning them from the + <seealso marker="#state callback">state callback</seealso>, from + <seealso marker="#Module:init/1"><c>Module:init/1</c></seealso> + or by giving them to + <seealso marker="#enter_loop/5"><c>enter_loop/5,6</c></seealso>. + </p> + <p> + Actions are executed in the containing list order. + </p> + <p> + Actions that set + <seealso marker="#type-transition_option">transition options</seealso> + override any previous of the same type, + so the last in the containing list wins. + For example, the last + <seealso marker="#type-event_timeout"><c>event_timeout()</c></seealso> + overrides any previous <c>event_timeout()</c> in the list. + </p> + <taglist> + <tag><c>hibernate</c></tag> + <item> + <p> + Sets the + <seealso marker="#type-transition_option"><c>transition_option()</c></seealso> + <seealso marker="#type-hibernate"><c>hibernate()</c></seealso> + for this state transition. + </p> + </item> + </taglist> + </desc> + </datatype> + <datatype> + <name name="timeout_action"/> + <desc> + <p> + These state transition actions can be invoked by + returning them from the + <seealso marker="#state callback">state callback</seealso>, from + <seealso marker="#Module:init/1"><c>Module:init/1</c></seealso> + or by giving them to + <seealso marker="#enter_loop/5"><c>enter_loop/5,6</c></seealso>. + </p> + <p> + These timeout actions sets timeout + <seealso marker="#type-transition_option">transition options</seealso>. + </p> + <taglist> + <tag><c>Time</c></tag> + <item> + <p> + Short for <c>{timeout,Time,Time}</c>, that is, + the time-out message is the time-out time. + This form exists to make the + <seealso marker="#state callback">state callback</seealso> + return value <c>{next_state,NextState,NewData,Time}</c> + allowed like for <c>gen_fsm</c>. + </p> + </item> + <tag><c>timeout</c></tag> + <item> + <p> + Sets the + <seealso marker="#type-transition_option"><c>transition_option()</c></seealso> + <seealso marker="#type-event_timeout"><c>event_timeout()</c></seealso> + to <c><anno>Time</anno></c> with <c><anno>EventContent</anno></c> + and time-out options + <seealso marker="#type-timeout_option"><c><anno>Options</anno></c></seealso>. + </p> + </item> + <tag><c>{timeout,<anno>Name</anno>}</c></tag> + <item> + <p> + Sets the + <seealso marker="#type-transition_option"><c>transition_option()</c></seealso> + <seealso marker="#type-generic_timeout"><c>generic_timeout()</c></seealso> + to <c><anno>Time</anno></c> for <c><anno>Name</anno></c> + with <c><anno>EventContent</anno></c> + and time-out options + <seealso marker="#type-timeout_option"><c><anno>Options</anno></c></seealso>. + </p> + </item> + <tag><c>state_timeout</c></tag> + <item> + <p> + Sets the + <seealso marker="#type-transition_option"><c>transition_option()</c></seealso> + <seealso marker="#type-state_timeout"><c>state_timeout()</c></seealso> + to <c><anno>Time</anno></c> with <c><anno>EventContent</anno></c> + and time-out options + <seealso marker="#type-timeout_option"><c><anno>Options</anno></c></seealso>. + </p> + </item> + </taglist> + </desc> + </datatype> + <datatype> + <name name="reply_action"/> + <desc> + <p> + This state transition action can be invoked by + returning it from the + <seealso marker="#state callback">state callback</seealso>, from + <seealso marker="#Module:init/1"><c>Module:init/1</c></seealso> + or by giving it to + <seealso marker="#enter_loop/5"><c>enter_loop/5,6</c></seealso>. + </p> + <p> + It does not set any + <seealso marker="#type-transition_option"> + <c>transition_option()</c> + </seealso> + but instead replies to a caller waiting for a reply in + <seealso marker="#call/2"><c>call/2</c></seealso>. + <c><anno>From</anno></c> must be the term from argument + <seealso marker="#type-event_type"><c>{call,<anno>From</anno>}</c></seealso> + in a call to a + <seealso marker="#state callback">state callback</seealso>. + </p> + <p> + Note that using this action from + <seealso marker="#Module:init/1"><c>Module:init/1</c></seealso> + or + <seealso marker="#enter_loop/5"><c>enter_loop/5,6</c></seealso> + would be weird on the border of witchcraft + since there has been no earlier call to a + <seealso marker="#state callback">state callback</seealso> + in this server. + </p> + </desc> + </datatype> + <datatype> + <name name="init_result"/> + <desc> + <p> + For a succesful initialization, + <c><anno>State</anno></c> is the initial + <seealso marker="#type-state"><c>state()</c></seealso> + and <c><anno>Data</anno></c> the initial server + <seealso marker="#type-data"><c>data()</c></seealso> + of the <c>gen_statem</c>. + </p> + <p> + The <seealso marker="#type-action"><c>Actions</c></seealso> + are executed when entering the first + <seealso marker="#type-state">state</seealso> just as for a + <seealso marker="#state callback">state callback</seealso>, + except that the action <c>postpone</c> is forced to + <c>false</c> since there is no event to postpone. + </p> + <p> + For an unsuccesful initialization, + <c>{stop,<anno>Reason</anno>}</c> + or <c>ignore</c> should be used; see + <seealso marker="#start_link/3"><c>start_link/3,4</c></seealso>. + </p> + </desc> + </datatype> + <datatype> + <name name="state_enter_result"/> + <desc> + <p> + <c><anno>State</anno></c> is the current state + and it can not be changed since the state callback + was called with a + <seealso marker="#type-state_enter"><em>state enter call</em></seealso>. + </p> + <taglist> + <tag><c>next_state</c></tag> + <item> + <p> + The <c>gen_statem</c> does a state transition to + <c><anno>State</anno></c>, which has to be + the current state, + sets <c><anno>NewData</anno></c>, + and executes all <c><anno>Actions</anno></c>. + </p> + </item> + </taglist> + </desc> + </datatype> + <datatype> + <name name="event_handler_result"/> + <desc> + <p> + <c><anno>StateType</anno></c> is + <seealso marker="#type-state_name"><c>state_name()</c></seealso> + if + <seealso marker="#type-callback_mode"><em>callback mode</em></seealso> + is <c>state_functions</c>, or + <seealso marker="#type-state"><c>state()</c></seealso> + if + <seealso marker="#type-callback_mode"><em>callback mode</em></seealso> + is <c>handle_event_function</c>. + </p> + <taglist> + <tag><c>next_state</c></tag> + <item> + <p> + The <c>gen_statem</c> does a state transition to + <c><anno>NextState</anno></c> + (which can be the same as the current state), + sets <c><anno>NewData</anno></c>, + and executes all <c><anno>Actions</anno></c>. + </p> + </item> + </taglist> + </desc> + </datatype> + <datatype> + <name name="state_callback_result"/> + <desc> + <p> + <c><anno>ActionType</anno></c> is + <seealso marker="#type-enter_action"><c>enter_action()</c></seealso> + if the state callback was called with a + <seealso marker="#type-state_enter"><em>state enter call</em></seealso> + and + <seealso marker="#type-action"><c>action()</c></seealso> + if the state callback was called with an event. + </p> + <taglist> + <tag><c>keep_state</c></tag> + <item> + <p> + The <c>gen_statem</c> keeps the current state, or + does a state transition to the current state if you like, + sets <c><anno>NewData</anno></c>, + and executes all <c><anno>Actions</anno></c>. + This is the same as + <c>{next_state,CurrentState,<anno>NewData</anno>,<anno>Actions</anno>}</c>. + </p> + </item> + <tag><c>keep_state_and_data</c></tag> + <item> + <p> + The <c>gen_statem</c> keeps the current state or + does a state transition to the current state if you like, + keeps the current server data, + and executes all <c><anno>Actions</anno></c>. + This is the same as + <c>{next_state,CurrentState,CurrentData,<anno>Actions</anno>}</c>. + </p> + </item> + <tag><c>repeat_state</c></tag> + <item> + <p> + The <c>gen_statem</c> keeps the current state, or + does a state transition to the current state if you like, + sets <c><anno>NewData</anno></c>, + and executes all <c><anno>Actions</anno></c>. + If the <c>gen_statem</c> runs with + <seealso marker="#type-state_enter"><em>state enter calls</em></seealso>, + the state enter call is repeated, see type + <seealso marker="#type-transition_option"><c>transition_option()</c></seealso>, + otherwise <c>repeat_state</c> is the same as + <c>keep_state</c>. + </p> + </item> + <tag><c>repeat_state_and_data</c></tag> + <item> + <p> + The <c>gen_statem</c> keeps the current state and data, or + does a state transition to the current state if you like, + and executes all <c><anno>Actions</anno></c>. + This is the same as + <c>{repeat_state,CurrentData,<anno>Actions</anno>}</c>. + If the <c>gen_statem</c> runs with + <seealso marker="#type-state_enter"><em>state enter calls</em></seealso>, + the state enter call is repeated, see type + <seealso marker="#type-transition_option"><c>transition_option()</c></seealso>, + otherwise <c>repeat_state_and_data</c> is the same as + <c>keep_state_and_data</c>. + </p> + </item> + <tag><c>stop</c></tag> + <item> + <p> + Terminates the <c>gen_statem</c> by calling + <seealso marker="#Module:terminate/3"><c>Module:terminate/3</c></seealso> + with <c>Reason</c> and + <c><anno>NewData</anno></c>, if specified. + </p> + </item> + <tag><c>stop_and_reply</c></tag> + <item> + <p> + Sends all <c><anno>Replies</anno></c>, + then terminates the <c>gen_statem</c> by calling + <seealso marker="#Module:terminate/3"><c>Module:terminate/3</c></seealso> + with <c>Reason</c> and + <c><anno>NewData</anno></c>, if specified. + </p> + </item> + </taglist> + <p> + All these terms are tuples or atoms and this property + will hold in any future version of <c>gen_statem</c>. + </p> + </desc> + </datatype> + </datatypes> + + <funcs> + <func> + <name name="call" arity="2"/> + <name name="call" arity="3"/> + <fsummary>Make a synchronous call to a <c>gen_statem</c>.</fsummary> + <desc> + <p> + Makes a synchronous call to the <c>gen_statem</c> + <seealso marker="#type-server_ref"><c><anno>ServerRef</anno></c></seealso> + by sending a request + and waiting until its reply arrives. + The <c>gen_statem</c> calls the + <seealso marker="#state callback">state callback</seealso> with + <seealso marker="#type-event_type"><c>event_type()</c></seealso> + <c>{call,From}</c> and event content + <c><anno>Request</anno></c>. + </p> + <p> + A <c><anno>Reply</anno></c> is generated when a + <seealso marker="#state callback">state callback</seealso> + returns with + <c>{reply,From,<anno>Reply</anno>}</c> as one + <seealso marker="#type-action"><c>action()</c></seealso>, + and that <c><anno>Reply</anno></c> becomes the return value + of this function. + </p> + <p> + <c><anno>Timeout</anno></c> is an integer > 0, + which specifies how many milliseconds to wait for a reply, + or the atom <c>infinity</c> to wait indefinitely, + which is the default. If no reply is received within + the specified time, the function call fails. + </p> + <note> + <p> + For <c><anno>Timeout</anno> < infinity</c>, + 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 + <c><anno>Timeout</anno> == infinity</c>. + </p> + </note> + <p> + <c><anno>Timeout</anno></c> can also be a tuple + <c>{clean_timeout,<anno>T</anno>}</c> or + <c>{dirty_timeout,<anno>T</anno>}</c>, where + <c><anno>T</anno></c> is the time-out time. + <c>{clean_timeout,<anno>T</anno>}</c> works like + just <c>T</c> described in the note above + and uses a proxy process + while <c>{dirty_timeout,<anno>T</anno>}</c> + bypasses the proxy process which is more lightweight. + </p> + <note> + <p> + If you combine catching exceptions from this function + with <c>{dirty_timeout,<anno>T</anno>}</c> + 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 + <c>{dirty_timeout,infinity}</c> or <c>infinity</c> + for example in the event of network problems. + So why not just let the calling process die + by not catching the exception? + </p> + </note> + <p> + The call can also fail, for example, if the <c>gen_statem</c> + dies before or during this function call. + </p> + </desc> + </func> + + <func> + <name name="cast" arity="2"/> + <fsummary>Send an asynchronous event to a <c>gen_statem</c>.</fsummary> + <desc> + <p> + Sends an asynchronous event to the <c>gen_statem</c> + <seealso marker="#type-server_ref"><c><anno>ServerRef</anno></c></seealso> + and returns <c>ok</c> immediately, + ignoring if the destination node or <c>gen_statem</c> + does not exist. + The <c>gen_statem</c> calls the + <seealso marker="#state callback">state callback</seealso> with + <seealso marker="#type-event_type"><c>event_type()</c></seealso> + <c>cast</c> and event content + <c><anno>Msg</anno></c>. + </p> + </desc> + </func> + + <func> + <name name="enter_loop" arity="4"/> + <fsummary>Enter the <c>gen_statem</c> receive loop.</fsummary> + <desc> + <p> + The same as + <seealso marker="#enter_loop/6"><c>enter_loop/6</c></seealso> + with <c>Actions = []</c> except that no + <seealso marker="#type-server_name"><c>server_name()</c></seealso> + must have been registered. This creates an anonymous server. + </p> + </desc> + </func> + + <func> + <name name="enter_loop" arity="5"/> + <fsummary>Enter the <c>gen_statem</c> receive loop.</fsummary> + <desc> + <p> + If <c><anno>Server_or_Actions</anno></c> is a <c>list()</c>, + the same as + <seealso marker="#enter_loop/6"><c>enter_loop/6</c></seealso> + except that no + <seealso marker="#type-server_name"><c>server_name()</c></seealso> + must have been registered and + <c>Actions = <anno>Server_or_Actions</anno></c>. + This creates an anonymous server. + </p> + <p> + Otherwise the same as + <seealso marker="#enter_loop/6"><c>enter_loop/6</c></seealso> + with + <c>Server = <anno>Server_or_Actions</anno></c> and + <c>Actions = []</c>. + </p> + </desc> + </func> + + <func> + <name name="enter_loop" arity="6"/> + <fsummary>Enter the <c>gen_statem</c> receive loop.</fsummary> + <desc> + <p> + Makes the calling process become a <c>gen_statem</c>. + Does not return, instead the calling process enters + the <c>gen_statem</c> receive loop and becomes + a <c>gen_statem</c> server. + The process <em>must</em> have been started + using one of the start functions in + <seealso marker="proc_lib"><c>proc_lib</c></seealso>. + The user is responsible for any initialization of the process, + including registering a name for it. + </p> + <p> + This function is useful when a more complex initialization + procedure is needed than + the <c>gen_statem</c> behavior provides. + </p> + <p> + <c><anno>Module</anno></c>, <c><anno>Opts</anno></c> + have the same meaning as when calling + <seealso marker="#start_link/3"><c>start[_link]/3,4</c></seealso>. + </p> + <p> + If <c><anno>Server</anno></c> is <c>self()</c> an anonymous + server is created just as when using + <seealso marker="#start_link/3"><c>start[_link]/3</c></seealso>. + If <c><anno>Server</anno></c> is a + <seealso marker="#type-server_name"><c>server_name()</c></seealso> + a named server is created just as when using + <seealso marker="#start_link/4"><c>start[_link]/4</c></seealso>. + However, the + <seealso marker="#type-server_name"><c>server_name()</c></seealso> + name must have been registered accordingly + <em>before</em> this function is called. + </p> + <p> + <c><anno>State</anno></c>, <c><anno>Data</anno></c>, + and <c><anno>Actions</anno></c> + have the same meanings as in the return value of + <seealso marker="#Module:init/1"><c>Module:init/1</c></seealso>. + Also, the callback module does not need to export a + <seealso marker="#Module:init/1"><c>Module:init/1</c></seealso> + function. + </p> + <p> + The function fails if the calling process was not started by a + <seealso marker="proc_lib"><c>proc_lib</c></seealso> + start function, or if it is not registered + according to + <seealso marker="#type-server_name"><c>server_name()</c></seealso>. + </p> + </desc> + </func> + + <func> + <name name="reply" arity="1"/> + <name name="reply" arity="2"/> + <fsummary>Reply to a caller.</fsummary> + <desc> + <p> + This function can be used by a <c>gen_statem</c> + to explicitly send a reply to a process that waits in + <seealso marker="#call/2"><c>call/2</c></seealso> + when the reply cannot be defined in + the return value of a + <seealso marker="#state callback">state callback</seealso>. + </p> + <p> + <c><anno>From</anno></c> must be the term from argument + <seealso marker="#type-event_type"><c>{call,<anno>From</anno>}</c></seealso> + to the + <seealso marker="#state callback">state callback</seealso>. + A reply or multiple replies canalso be sent + using one or several + <seealso marker="#type-reply_action"><c>reply_action()</c></seealso>s + from a + <seealso marker="#state callback">state callback</seealso>. + </p> + <note> + <p> + A reply sent with this function is not visible + in <seealso marker="sys"><c>sys</c></seealso> debug output. + </p> + </note> + </desc> + </func> + + <func> + <name name="start" arity="3"/> + <name name="start" arity="4"/> + <fsummary>Create a standalone <c>gen_statem</c> process.</fsummary> + <desc> + <p> + Creates a standalone <c>gen_statem</c> process according to + OTP design principles (using + <seealso marker="proc_lib"><c>proc_lib</c></seealso> + primitives). + As it does not get linked to the calling process, + this start function cannot be used by a supervisor + to start a child. + </p> + <p> + For a description of arguments and return values, see + <seealso marker="#start_link/3"><c>start_link/3,4</c></seealso>. + </p> + </desc> + </func> + + <func> + <name name="start_link" arity="3"/> + <name name="start_link" arity="4"/> + <fsummary>Create a linked <c>gen_statem</c> process.</fsummary> + <desc> + <p> + Creates a <c>gen_statem</c> process according + to OTP design principles + (using + <seealso marker="proc_lib"><c>proc_lib</c></seealso> + primitives) + that is linked to the calling process. + This is essential when the <c>gen_statem</c> must be part of + a supervision tree so it gets linked to its supervisor. + </p> + <p> + The <c>gen_statem</c> process calls + <seealso marker="#Module:init/1"><c>Module:init/1</c></seealso> + to initialize the server. To ensure a synchronized startup + procedure, <c>start_link/3,4</c> does not return until + <seealso marker="#Module:init/1"><c>Module:init/1</c></seealso> + has returned. + </p> + <p> + <c><anno>ServerName</anno></c> specifies the + <seealso marker="#type-server_name"><c>server_name()</c></seealso> + to register for the <c>gen_statem</c>. + If the <c>gen_statem</c> is started with <c>start_link/3</c>, + no <c><anno>ServerName</anno></c> is provided and + the <c>gen_statem</c> is not registered. + </p> + <p><c><anno>Module</anno></c> is the name of the callback module.</p> + <p> + <c><anno>Args</anno></c> is an arbitrary term that is passed as + the argument to + <seealso marker="#Module:init/1"><c>Module:init/1</c></seealso>. + </p> + <list type="bulleted"> + <item> + <p> + If option <c>{timeout,Time}</c> is present in + <c><anno>Opts</anno></c>, the <c>gen_statem</c> + is allowed to spend <c>Time</c> milliseconds initializing + or it terminates and the start function returns + <seealso marker="#type-start_ret"><c>{error,timeout}</c></seealso>. + </p> + </item> + <item> + <p>If option<seealso marker="#type-hibernate_after_opt"><c>{hibernate_after,HibernateAfterTimeout}</c></seealso> is present, the <c>gen_statem</c> + process awaits any message for <c>HibernateAfterTimeout</c> milliseconds and + if no message is received, the process goes into hibernation automatically + (by calling <seealso marker="proc_lib#hibernate/3"><c>proc_lib:hibernate/3</c></seealso>). + </p> + </item> + <item> + <p> + If option + <seealso marker="#type-debug_opt"><c>{debug,Dbgs}</c></seealso> + is present in <c><anno>Opts</anno></c>, debugging through + <seealso marker="sys"><c>sys</c></seealso> is activated. + </p> + </item> + <item> + <p> + If option <c>{spawn_opt,SpawnOpts}</c> is present in + <c><anno>Opts</anno></c>, <c>SpawnOpts</c> is passed + as option list to + <seealso marker="erts:erlang#spawn_opt/2"><c>erlang:spawn_opt/2</c></seealso>, + which is used to spawn the <c>gen_statem</c> process. + </p> + </item> + </list> + <note> + <p> + Using spawn option <c>monitor</c> is not + allowed, it causes this function to fail with reason + <c>badarg</c>. + </p> + </note> + <p> + If the <c>gen_statem</c> is successfully created + and initialized, this function returns + <seealso marker="#type-start_ret"><c>{ok,Pid}</c></seealso>, + where <c>Pid</c> is the <c>pid()</c> + of the <c>gen_statem</c>. + If a process with the specified <c><anno>ServerName</anno></c> + exists already, this function returns + <seealso marker="#type-start_ret"><c>{error,{already_started,Pid}}</c></seealso>, + where <c>Pid</c> is the <c>pid()</c> of that process. + </p> + <p> + If <c>Module:init/1</c> fails with <c>Reason</c>, + this function returns + <seealso marker="#type-start_ret"><c>{error,Reason}</c></seealso>. + If <c>Module:init/1</c> returns + <seealso marker="#type-start_ret"><c>{stop,Reason}</c></seealso> + or + <seealso marker="#type-start_ret"><c>ignore</c></seealso>, + the process is terminated and this function + returns + <seealso marker="#type-start_ret"><c>{error,Reason}</c></seealso> + or + <seealso marker="#type-start_ret"><c>ignore</c></seealso>, + respectively. + </p> + </desc> + </func> + + <func> + <name name="stop" arity="1"/> + <fsummary>Synchronously stop a generic server.</fsummary> + <desc> + <p> + The same as + <seealso marker="#stop/3"><c>stop(<anno>ServerRef</anno>, normal, infinity)</c></seealso>. + </p> + </desc> + </func> + + <func> + <name name="stop" arity="3"/> + <fsummary>Synchronously stop a generic server.</fsummary> + <desc> + <p> + Orders the <c>gen_statem</c> + <seealso marker="#type-server_ref"><c><anno>ServerRef</anno></c></seealso> + to exit with the specified <c><anno>Reason</anno></c> + and waits for it to terminate. + The <c>gen_statem</c> calls + <seealso marker="#Module:terminate/3"><c>Module:terminate/3</c></seealso> + before exiting. + </p> + <p> + This function returns <c>ok</c> if the server terminates + with the expected reason. Any other reason than <c>normal</c>, + <c>shutdown</c>, or <c>{shutdown,Term}</c> causes an + error report to be issued through + <seealso marker="kernel:logger"><c>logger(3)</c></seealso>. + The default <c><anno>Reason</anno></c> is <c>normal</c>. + </p> + <p> + <c><anno>Timeout</anno></c> is an integer > 0, + which specifies how many milliseconds to wait for the server to + terminate, or the atom <c>infinity</c> to wait indefinitely. + Defaults to <c>infinity</c>. + If the server does not terminate within the specified time, + a <c>timeout</c> exception is raised. + </p> + <p> + If the process does not exist, a <c>noproc</c> exception + is raised. + </p> + </desc> + </func> + </funcs> + + <section> + <title>Callback Functions</title> + <p> + The following functions are to be exported from a + <c>gen_statem</c> callback module. + </p> + </section> + + <funcs> + <func> + <name>Module:callback_mode() -> CallbackMode</name> + <fsummary>Update the internal state during upgrade/downgrade.</fsummary> + <type> + <v> + CallbackMode = + <seealso marker="#type-callback_mode">callback_mode()</seealso> | + [ <seealso marker="#type-callback_mode">callback_mode()</seealso> + | <seealso marker="#type-state_enter">state_enter()</seealso> ] + </v> + </type> + <desc> + <p> + This function is called by a <c>gen_statem</c> + when it needs to find out the + <seealso marker="#type-callback_mode"><em>callback mode</em></seealso> + of the callback module. The value is cached by <c>gen_statem</c> + for efficiency reasons, so this function is only called + once after server start and after code change, + but before the first + <seealso marker="#state callback">state callback</seealso> + in the current code version is called. + More occasions may be added in future versions + of <c>gen_statem</c>. + </p> + <p> + Server start happens either when + <seealso marker="#Module:init/1"><c>Module:init/1</c></seealso> + returns or when + <seealso marker="#enter_loop/4"><c>enter_loop/4-6</c></seealso> + is called. Code change happens when + <seealso marker="#Module:code_change/4"><c>Module:code_change/4</c></seealso> + returns. + </p> + <p> + The <c>CallbackMode</c> is either just + <seealso marker="#type-callback_mode"><c>callback_mode()</c></seealso> + or a list containing + <seealso marker="#type-callback_mode"><c>callback_mode()</c></seealso> + and possibly the atom + <seealso marker="#type-state_enter"><c>state_enter</c></seealso>. + </p> + <note> + <p> + If this function's body does not return an inline constant + value the callback module is doing something strange. + </p> + </note> + </desc> + </func> + + <func> + <name>Module:code_change(OldVsn, OldState, OldData, Extra) -> + Result + </name> + <fsummary>Update the internal state during upgrade/downgrade.</fsummary> + <type> + <v>OldVsn = Vsn | {down,Vsn}</v> + <v> Vsn = term()</v> + <v>OldState = NewState = term()</v> + <v>Extra = term()</v> + <v>Result = {ok,NewState,NewData} | Reason</v> + <v> + OldState = NewState = + <seealso marker="#type-state">state()</seealso> + </v> + <v> + OldData = NewData = + <seealso marker="#type-data">data()</seealso> + </v> + <v>Reason = term()</v> + </type> + <desc> + <note> + <p> + This callback is optional, so callback modules need not export it. + If a release upgrade/downgrade with + <c>Change={advanced,Extra}</c> + specified in the <c>.appup</c> file is made + when <c>code_change/4</c> is not implemented + the process will crash with exit reason <c>undef</c>. + </p> + </note> + <p> + This function is called by a <c>gen_statem</c> when it is to + update its internal state during a release upgrade/downgrade, + that is, when the instruction <c>{update,Module,Change,...}</c>, + where <c>Change={advanced,Extra}</c>, is specified in the + <seealso marker="sasl:appup"><c>appup</c></seealso> + file. For more information, see + <seealso marker="doc/design_principles:release_handling#instr">OTP Design Principles</seealso>. + </p> + <p> + For an upgrade, <c>OldVsn</c> is <c>Vsn</c>, and + for a downgrade, <c>OldVsn</c> is + <c>{down,Vsn}</c>. <c>Vsn</c> is defined by the <c>vsn</c> + attribute(s) of the old version of the callback module + <c>Module</c>. If no such attribute is defined, the version + is the checksum of the Beam file. + </p> + <p> + <c>OldState</c> and <c>OldData</c> is the internal state + of the <c>gen_statem</c>. + </p> + <p> + <c>Extra</c> is passed "as is" from the <c>{advanced,Extra}</c> + part of the update instruction. + </p> + <p> + If successful, the function must return the updated + internal state in an + <c>{ok,NewState,NewData}</c> tuple. + </p> + <p> + If the function returns a failure <c>Reason</c>, the ongoing + upgrade fails and rolls back to the old release. + Note that <c>Reason</c> can not be an <c>{ok,_,_}</c> tuple + since that will be regarded as a + <c>{ok,NewState,NewData}</c> tuple, + and that a tuple matching <c>{ok,_}</c> + is an also invalid failure <c>Reason</c>. + It is recommended to use an atom as <c>Reason</c> since + it will be wrapped in an <c>{error,Reason}</c> tuple. + </p> + <p> + Also note when upgrading a <c>gen_statem</c>, + this function and hence + the <c>Change={advanced,Extra}</c> parameter in the + <seealso marker="sasl:appup"><c>appup</c></seealso> file + is not only needed to update the internal state + or to act on the <c>Extra</c> argument. + It is also needed if an upgrade or downgrade should change + <seealso marker="#type-callback_mode"><em>callback mode</em></seealso>, + or else the callback mode after the code change + will not be honoured, + most probably causing a server crash. + </p> + </desc> + </func> + + <func> + <name>Module:init(Args) -> Result(StateType)</name> + <fsummary> + Initializing process and internal state. + </fsummary> + <type> + <v>Args = term()</v> + <v> + Result(StateType) = + <seealso marker="#type-init_result">init_result(StateType)</seealso> + </v> + </type> + <desc> + <marker id="Module:init-1"/> + <p> + Whenever a <c>gen_statem</c> is started using + <seealso marker="#start_link/3"><c>start_link/3,4</c></seealso> + or + <seealso marker="#start/3"><c>start/3,4</c></seealso>, + this function is called by the new process to initialize + the implementation state and server data. + </p> + <p> + <c>Args</c> is the <c>Args</c> argument provided to that start + function. + </p> + <note> + <p> + Note that if the <c>gen_statem</c> is started through + <seealso marker="proc_lib"><c>proc_lib</c></seealso> + and + <seealso marker="#enter_loop/4"><c>enter_loop/4-6</c></seealso>, + this callback will never be called. + Since this callback is not optional it can + in that case be implemented as: + </p> + <pre> +init(Args) -> erlang:error(not_implemented, [Args]).</pre> + </note> + </desc> + </func> + + <func> + <name>Module:format_status(Opt, [PDict,State,Data]) -> + Status + </name> + <fsummary>Optional function for providing a term describing the + current <c>gen_statem</c> status.</fsummary> + <type> + <v>Opt = normal | terminate</v> + <v>PDict = [{Key, Value}]</v> + <v> + State = + <seealso marker="#type-state">state()</seealso> + </v> + <v> + Data = + <seealso marker="#type-data">data()</seealso> + </v> + <v>Key = term()</v> + <v>Value = term()</v> + <v>Status = term()</v> + </type> + <desc> + <note> + <p> + This callback is optional, so a callback module does not need + to export it. The <c>gen_statem</c> module provides a default + implementation of this function that returns + <c>{State,Data}</c>. + </p> + <p> + If this callback is exported but fails, + to hide possibly sensitive data, + the default function will instead return <c>{State,Info}</c>, + where <c>Info</c> says nothing but the fact that + <c>format_status/2</c> has crashed. + </p> + </note> + <p>This function is called by a <c>gen_statem</c> process when + any of the following apply:</p> + <list type="bulleted"> + <item> + One of + <seealso marker="sys#get_status/1"><c>sys:get_status/1,2</c></seealso> + is invoked to get the <c>gen_statem</c> status. <c>Opt</c> is set + to the atom <c>normal</c> for this case. + </item> + <item> + The <c>gen_statem</c> terminates abnormally and logs an error. + <c>Opt</c> is set to the atom <c>terminate</c> for this case. + </item> + </list> + <p> + This function is useful for changing the form and + appearance of the <c>gen_statem</c> status for these cases. A + callback module wishing to change the + <seealso marker="sys#get_status/1"><c>sys:get_status/1,2</c></seealso> + return value and how + its status appears in termination error logs exports an + instance of <c>format_status/2</c>, which returns a term + describing the current status of the <c>gen_statem</c>. + </p> + <p> + <c>PDict</c> is the current value of the process dictionary + of the <c>gen_statem</c>. + </p> + <p> + <seealso marker="#type-state"><c>State</c></seealso> + is the internal state of the <c>gen_statem</c>. + </p> + <p> + <seealso marker="#type-data"><c>Data</c></seealso> + is the internal server data of the <c>gen_statem</c>. + </p> + <p> + The function is to return <c>Status</c>, a term that + contains the appropriate details + of the current state and status of + the <c>gen_statem</c>. There are no restrictions on the + form <c>Status</c> can take, but for the + <seealso marker="sys#get_status/1"><c>sys:get_status/1,2</c></seealso> + case (when <c>Opt</c> + is <c>normal</c>), the recommended form for + the <c>Status</c> value is <c>[{data, [{"State", + Term}]}]</c>, where <c>Term</c> provides relevant details of + the <c>gen_statem</c> state. Following this recommendation is not + required, but it makes the callback module status + consistent with the rest of the + <seealso marker="sys#get_status/1"><c>sys:get_status/1,2</c></seealso> + return value. + </p> + <p> + 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. + </p> + </desc> + </func> + + <func> + <name>Module:StateName(enter, OldState, Data) -> + StateEnterResult(StateName) + </name> + <name>Module:StateName(EventType, EventContent, Data) -> + StateFunctionResult + </name> + <name>Module:handle_event(enter, OldState, State, Data) -> + StateEnterResult(State) + </name> + <name>Module:handle_event(EventType, EventContent, State, Data) -> + HandleEventResult + </name> + <fsummary>Handle an event.</fsummary> + <type> + <v> + EventType = + <seealso marker="#type-event_type">event_type()</seealso> + </v> + <v>EventContent = term()</v> + <v> + State = + <seealso marker="#type-state">state()</seealso> + </v> + <v> + Data = NewData = + <seealso marker="#type-data">data()</seealso> + </v> + <v> + StateEnterResult(StateName) = + <seealso marker="#type-state_enter_result">state_enter_result(StateName)</seealso> + </v> + <v> + StateFunctionResult = + <seealso marker="#type-event_handler_result">event_handler_result</seealso>(<seealso marker="#type-state_name">state_name()</seealso>) + </v> + <v> + StateEnterResult(State) = + <seealso marker="#type-state_enter_result">state_enter_result(State)</seealso> + </v> + <v> + HandleEventResult = + <seealso marker="#type-event_handler_result">event_handler_result</seealso>(<seealso marker="#type-state">state()</seealso>) + </v> + </type> + <desc> + <p> + Whenever a <c>gen_statem</c> receives an event from + <seealso marker="#call/2"><c>call/2</c></seealso>, + <seealso marker="#cast/2"><c>cast/2</c></seealso>, or + as a normal process message, one of these functions is called. If + <seealso marker="#type-callback_mode"><em>callback mode</em></seealso> + is <c>state_functions</c>, <c>Module:StateName/3</c> is called, + and if it is <c>handle_event_function</c>, + <c>Module:handle_event/4</c> is called. + </p> + <p> + If <c>EventType</c> is + <seealso marker="#type-event_type"><c>{call,From}</c></seealso>, + the caller waits for a reply. The reply can be sent + from this or from any other + <seealso marker="#state callback">state callback</seealso> + by returning with <c>{reply,From,Reply}</c> in + <seealso marker="#type-action"><c>Actions</c></seealso>, in + <seealso marker="#type-reply_action"><c>Replies</c></seealso>, + or by calling + <seealso marker="#reply/2"><c>reply(From, Reply)</c></seealso>. + </p> + <p> + If this function returns with a next state that + does not match equal (<c>=/=</c>) to the current state, + all postponed events are retried in the next state. + </p> + <p> + The only difference between <c>StateFunctionResult</c> and + <c>HandleEventResult</c> is that for <c>StateFunctionResult</c> + the next state must be an atom, but for <c>HandleEventResult</c> + there is no restriction on the next state. + </p> + <p> + For options that can be set and actions that can be done + by <c>gen_statem</c> after returning from this function, + see <seealso marker="#type-action"><c>action()</c></seealso>. + </p> + <p> + When the <c>gen_statem</c> runs with + <seealso marker="#type-state_enter">state enter calls</seealso>, + these functions are also called with arguments + <c>(enter, OldState, ...)</c> whenever the state changes. + In this case there are some restrictions on the + <seealso marker="#type-enter_action">actions</seealso> + that may be returned: + <seealso marker="#type-postpone"><c>postpone()</c></seealso> + is not allowed since a <em>state enter call</em> is not + an event so there is no event to postpone, and + <seealso marker="#type-action"><c>{next_event,_,_}</c></seealso> + is not allowed since using <em>state enter calls</em> + should not affect how events are consumed and produced. + You may also not change states from this call. + Should you return <c>{next_state,NextState, ...}</c> + with <c>NextState =/= State</c> the <c>gen_statem</c> crashes. + Note that it is actually allowed to use + <c>{repeat_state, NewData, ...}</c> although it makes little + sense since you immediately will be called again with a new + <em>state enter call</em> making this just a weird way + of looping, and there are better ways to loop in Erlang. + If you do not update <c>NewData</c> and have some + loop termination condition, or if you use + <c>{repeat_state_and_data, _}</c> or + <c>repeat_state_and_data</c> you have an infinite loop! + You are advised to use <c>{keep_state,...}</c>, + <c>{keep_state_and_data,_}</c> or + <c>keep_state_and_data</c> + since changing states from a <em>state enter call</em> + is not possible anyway. + </p> + <p> + Note the fact that you can use + <seealso marker="erts:erlang#throw/1"><c>throw</c></seealso> + to return the result, which can be useful. + For example to bail out with <c>throw(keep_state_and_data)</c> + from deep within complex code that can not + return <c>{next_state,State,Data}</c> because + <c>State</c> or <c>Data</c> is no longer in scope. + </p> + </desc> + </func> + + <func> + <name>Module:terminate(Reason, State, Data) -> Ignored</name> + <fsummary>Clean up before termination.</fsummary> + <type> + <v>Reason = normal | shutdown | {shutdown,term()} | term()</v> + <v>State = <seealso marker="#type-state">state()</seealso></v> + <v>Data = <seealso marker="#type-data">data()</seealso></v> + <v>Ignored = term()</v> + </type> + <desc> + <note> + <p>This callback is optional, so callback modules need not + export it. The <c>gen_statem</c> module provides a default + implementation without cleanup.</p> + </note> + <p> + This function is called by a <c>gen_statem</c> + when it is about to terminate. It is to be the opposite of + <seealso marker="#Module:init/1"><c>Module:init/1</c></seealso> + and do any necessary cleaning up. When it returns, + the <c>gen_statem</c> terminates with <c>Reason</c>. The return + value is ignored.</p> + <p> + <c>Reason</c> is a term denoting the stop reason and + <seealso marker="#type-state"><c>State</c></seealso> + is the internal state of the <c>gen_statem</c>. + </p> + <p> + <c>Reason</c> depends on why the <c>gen_statem</c> + is terminating. + If it is because another callback function has returned, a + stop tuple <c>{stop,Reason}</c> in + <seealso marker="#type-action"><c>Actions</c></seealso>, + <c>Reason</c> has the value specified in that tuple. + If it is because of a failure, <c>Reason</c> is the error reason. + </p> + <p> + If the <c>gen_statem</c> is part of a supervision tree and is + ordered by its supervisor to terminate, this function is + called with <c>Reason = shutdown</c> if both the following + conditions apply:</p> + <list type="bulleted"> + <item> + <p> + The <c>gen_statem</c> has been set + to trap exit signals. + </p> + </item> + <item> + <p> + The shutdown strategy as defined in the supervisor's + child specification is an integer time-out value, not + <c>brutal_kill</c>. + </p> + </item> + </list> + <p> + Even if the <c>gen_statem</c> is <em>not</em> + part of a supervision tree, this function is called + if it receives an <c>'EXIT'</c> message from its parent. + <c>Reason</c> is the same as + in the <c>'EXIT'</c> message. + </p> + <p> + Otherwise, the <c>gen_statem</c> is immediately terminated. + </p> + <p> + Notice that for any other reason than <c>normal</c>, + <c>shutdown</c>, or <c>{shutdown,Term}</c>, + the <c>gen_statem</c> is assumed to terminate because of an error + and an error report is issued using + <seealso marker="kernel:logger"><c>logger(3)</c></seealso>. + </p> + </desc> + </func> + </funcs> + + <section> + <title>See Also</title> + <p> + <seealso marker="gen_event"><c>gen_event(3)</c></seealso>, + <seealso marker="gen_fsm"><c>gen_fsm(3)</c></seealso>, + <seealso marker="gen_server"><c>gen_server(3)</c></seealso>, + <seealso marker="proc_lib"><c>proc_lib(3)</c></seealso>, + <seealso marker="supervisor"><c>supervisor(3)</c></seealso>, + <seealso marker="sys"><c>sys(3)</c></seealso>. + </p> + </section> +</erlref> |