aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/stdlib/doc/src/gen_statem.xml296
-rw-r--r--system/doc/design_principles/statem.xml184
2 files changed, 145 insertions, 335 deletions
diff --git a/lib/stdlib/doc/src/gen_statem.xml b/lib/stdlib/doc/src/gen_statem.xml
index be90488a1f..b1d9799917 100644
--- a/lib/stdlib/doc/src/gen_statem.xml
+++ b/lib/stdlib/doc/src/gen_statem.xml
@@ -84,9 +84,7 @@
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>.
+ <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
@@ -136,28 +134,23 @@ erlang:'!' -----> Module:StateName/3
<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 function name; see
- <seealso marker="#Module:StateName/3">
- <c>Module:StateName/3</c>
- </seealso>.
+ <seealso marker="#Module:StateName/3"><c>Module:StateName/3</c></seealso>.
This gathers all code for a specific state
in one function and hence dispatches on state first.
Notice that in this mode
the mandatory callback function
- <seealso marker="#Module:terminate/3">
- <c>Module:terminate/3</c>
- </seealso> makes the state name <c>terminate</c> unusable.
+ <seealso marker="#Module:terminate/3"><c>Module:terminate/3</c></seealso>
+ makes the state name <c>terminate</c> unusable.
</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 function name is
- <seealso marker="#Module:handle_event/4">
- <c>Module:handle_event/4</c>
- </seealso>.
+ <seealso marker="#Module:handle_event/4"><c>Module:handle_event/4</c></seealso>.
This makes it easy to dispatch on state or on event as you desire.
Be careful about which events you handle in which
- states so that you do not accidentally postpone one event
+ states so that you do not accidentally postpone an event
forever creating an infinite busy loop.
</p>
<p>
@@ -178,15 +171,12 @@ erlang:'!' -----> Module:StateName/3
<p>
The <seealso marker="#state_function">state function</seealso>
can insert events using the
- <seealso marker="#type-action">
- <c>action()</c> <c>next_event</c>
- </seealso>
+ <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 function. That is, as if it is
the oldest incoming event. A dedicated
- <seealso marker="#type-event_type">
- <c>event_type()</c>
- </seealso>
+ <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>
@@ -206,21 +196,18 @@ erlang:'!' -----> Module:StateName/3
</note>
<p>
For the details of a state transition, see type
- <seealso marker="#type-transition_option">
- <c>transition_option()</c>
- </seealso>.
+ <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>.
+ 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>.
+ <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
@@ -229,9 +216,7 @@ erlang:'!' -----> Module:StateName/3
</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>.
+ <seealso marker="proc_lib#hibernate/3"><c>proc_lib:hibernate/3</c></seealso>.
It is done when a
<seealso marker="#state_function">state function</seealso> or
<seealso marker="#Module:init/1"><c>Module:init/1</c></seealso>
@@ -242,9 +227,7 @@ erlang:'!' -----> Module:StateName/3
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>.
+ <seealso marker="erts:erlang#hibernate/3"><c>erlang:hibernate/3</c></seealso>.
</p>
</description>
@@ -257,7 +240,7 @@ erlang:'!' -----> Module:StateName/3
<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 on.
+ pushed to switch on.
</p>
<p>The following is the complete callback module file
<c>pushbutton.erl</c>:</p>
@@ -381,13 +364,10 @@ handle_event(_, _, State, Data) ->
<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>
+ <seealso marker="#start_link/3"><c>start_link/3</c></seealso>
and
- <seealso marker="#type-server_ref">
- <c>server_ref()</c>
- </seealso> below.
+ <seealso marker="#type-server_ref"><c>server_ref()</c></seealso>
+ below.
</p>
</desc>
</datatype>
@@ -398,14 +378,12 @@ handle_event(_, _, State, Data) ->
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>
+ <seealso marker="#type-server_name"><c>server_name()</c></seealso>
above.
</p>
<p>It can be:</p>
<taglist>
- <tag><c>pid()</c> | <c>LocalName</c></tag>
+ <tag><c>pid() | LocalName</c></tag>
<item>
<p>
The <c>gen_statem</c> is locally registered.
@@ -421,21 +399,21 @@ handle_event(_, _, State, Data) ->
<tag><c>{global,GlobalName}</c></tag>
<item>
<p>
- The <c>gen_statem</c> is globally registered
- in <seealso marker="kernel:global"><c>kernel:global</c></seealso>.
+ The <c>gen_statem</c> is globally registered in
+ <seealso marker="kernel:global"><c>kernel:global</c></seealso>.
</p>
</item>
<tag><c>{via,RegMod,ViaName}</c></tag>
<item>
<p>
- The <c>gen_statem</c> is registered through
+ 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>kernel:global</c></seealso>.
+ which are to behave like the corresponding functions in
+ <seealso marker="kernel:global"><c>kernel:global</c></seealso>.
Thus, <c>{via,global,GlobalName}</c> is the same as
<c>{global,GlobalName}</c>.
</p>
@@ -482,9 +460,7 @@ handle_event(_, _, State, Data) ->
<desc>
<p>
Destination to use when replying through, for example, the
- <seealso marker="#type-action">
- <c>action()</c>
- </seealso>
+ <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>.
@@ -554,9 +530,7 @@ handle_event(_, _, State, Data) ->
or when calling
<seealso marker="#enter_loop/5"><c>enter_loop/5,6,7</c></seealso>,
and with the return value from
- <seealso marker="#Module:code_change/4">
- <c>Module:code_change/4</c>
- </seealso>.
+ <seealso marker="#Module:code_change/4"><c>Module:code_change/4</c></seealso>.
</p>
<taglist>
<tag><c>state_functions</c></tag>
@@ -565,9 +539,7 @@ handle_event(_, _, State, Data) ->
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>,
+ <seealso marker="#Module:StateName/3"><c>Module:StateName/3</c></seealso>,
is used.
</p>
</item>
@@ -575,9 +547,7 @@ handle_event(_, _, State, Data) ->
<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>
+ <seealso marker="#Module:handle_event/4"><c>Module:handle_event/4</c></seealso>
is used for all states.
</p>
</item>
@@ -604,9 +574,7 @@ handle_event(_, _, State, Data) ->
<item>
<p>
If
- <seealso marker="#type-postpone">
- <c>postpone()</c>
- </seealso>
+ <seealso marker="#type-postpone"><c>postpone()</c></seealso>
is <c>true</c>,
the current event is postponed.
</p>
@@ -620,9 +588,7 @@ handle_event(_, _, State, Data) ->
<item>
<p>
All events stored with
- <seealso marker="#type-action">
- <c>action()</c>
- </seealso>
+ <seealso marker="#type-action"><c>action()</c></seealso>
<c>next_event</c>
are inserted in the queue to be processed before
all other events.
@@ -631,13 +597,9 @@ handle_event(_, _, State, Data) ->
<item>
<p>
If an
- <seealso marker="#type-event_timeout">
- <c>event_timeout()</c>
- </seealso>
+ <seealso marker="#type-event_timeout"><c>event_timeout()</c></seealso>
is set through
- <seealso marker="#type-action">
- <c>action()</c>
- </seealso>
+ <seealso marker="#type-action"><c>action()</c></seealso>
<c>timeout</c>,
an event timer can be started or a time-out zero event
can be enqueued.
@@ -651,9 +613,7 @@ handle_event(_, _, State, Data) ->
otherwise the <c>gen_statem</c> goes into <c>receive</c>
or hibernation
(if
- <seealso marker="#type-hibernate">
- <c>hibernate()</c>
- </seealso>
+ <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
@@ -681,16 +641,13 @@ handle_event(_, _, State, Data) ->
<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>
+ <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.
If there are enqueued events,
to prevent receiving any new event, an
- <seealso marker="erts:erlang#garbage_collect/0">
- <c>erlang:garbage_collect/0</c>
- </seealso> is done instead to simulate
+ <seealso marker="erts:erlang#garbage_collect/0"><c>erlang:garbage_collect/0</c></seealso>
+ is done instead to simulate
that the <c>gen_statem</c> entered hibernation
and immediately got awakened by the oldest enqueued event.
</p>
@@ -731,8 +688,8 @@ handle_event(_, _, State, Data) ->
<p>
These state transition actions can be invoked by
returning them from the
- <seealso marker="#state_function">state function</seealso>,
- from <seealso marker="#Module:init/1"><c>Module:init/1</c></seealso>
+ <seealso marker="#state_function">state function</seealso>, from
+ <seealso marker="#Module:init/1"><c>Module:init/1</c></seealso>
or by giving them to
<seealso marker="#enter_loop/6"><c>enter_loop/6,7</c></seealso>.
</p>
@@ -741,15 +698,11 @@ handle_event(_, _, State, Data) ->
</p>
<p>
Actions that set
- <seealso marker="#type-transition_option">
- transition options
- </seealso>
+ <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>
+ <seealso marker="#type-event_timeout"><c>event_timeout()</c></seealso>
overrides any other <c>event_timeout()</c> in the list.
</p>
<taglist>
@@ -757,12 +710,8 @@ handle_event(_, _, State, Data) ->
<item>
<p>
Sets the
- <seealso marker="#type-transition_option">
- <c>transition_option()</c>
- </seealso>
- <seealso marker="#type-postpone">
- <c>postpone()</c>
- </seealso>
+ <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>
@@ -775,12 +724,8 @@ handle_event(_, _, State, Data) ->
<item>
<p>
Sets the
- <seealso marker="#type-transition_option">
- <c>transition_option()</c>
- </seealso>
- <seealso marker="#type-hibernate">
- <c>hibernate()</c>
- </seealso>
+ <seealso marker="#type-transition_option"><c>transition_option()</c></seealso>
+ <seealso marker="#type-hibernate"><c>hibernate()</c></seealso>
for this state transition.
</p>
</item>
@@ -792,22 +737,16 @@ handle_event(_, _, State, Data) ->
This form exists to make the
<seealso marker="#state_function">state function</seealso>
return value <c>{next_state,NextState,NewData,Timeout}</c>
- allowed like for
- <seealso marker="gen_fsm#Module:StateName/2">
- <c>gen_fsm:Module:StateName/2</c>
- </seealso>.
+ allowed like for <c>gen_fsm</c>'s
+ <seealso marker="gen_fsm#Module:StateName/2"><c>Module:StateName/2</c></seealso>.
</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>
+ <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>.
</p>
</item>
@@ -832,9 +771,7 @@ handle_event(_, _, State, Data) ->
</p>
<p>
An event of type
- <seealso marker="#type-event_type">
- <c>internal</c>
- </seealso>
+ <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>
@@ -849,9 +786,7 @@ handle_event(_, _, State, Data) ->
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>
+ <seealso marker="#type-event_type"><c>{call,<anno>From</anno>}</c></seealso>
to the
<seealso marker="#state_function">state function</seealso>.
</p>
@@ -907,9 +842,7 @@ handle_event(_, _, State, Data) ->
<item>
<p>
Terminates the <c>gen_statem</c> by calling
- <seealso marker="#Module:terminate/3">
- <c>Module:terminate/3</c>
- </seealso>
+ <seealso marker="#Module:terminate/3"><c>Module:terminate/3</c></seealso>
with <c>Reason</c> and
<c><anno>NewData</anno></c>, if specified.
</p>
@@ -919,9 +852,7 @@ handle_event(_, _, State, Data) ->
<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>
+ <seealso marker="#Module:terminate/3"><c>Module:terminate/3</c></seealso>
with <c>Reason</c> and
<c><anno>NewData</anno></c>, if specified.
</p>
@@ -965,9 +896,7 @@ handle_event(_, _, State, Data) ->
<desc>
<p>
Makes a synchronous call to the <c>gen_statem</c>
- <seealso marker="#type-server_ref">
- <c><anno>ServerRef</anno></c>
- </seealso>
+ <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
@@ -1015,9 +944,7 @@ handle_event(_, _, State, Data) ->
<desc>
<p>
Sends an asynchronous event to the <c>gen_statem</c>
- <seealso marker="#type-server_ref">
- <c><anno>ServerRef</anno></c>
- </seealso>
+ <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.
@@ -1038,9 +965,7 @@ handle_event(_, _, State, Data) ->
The same as
<seealso marker="#enter_loop/7"><c>enter_loop/7</c></seealso>
except that no
- <seealso marker="#type-server_name">
- <c>server_name()</c>
- </seealso>
+ <seealso marker="#type-server_name"><c>server_name()</c></seealso>
must have been registered.
</p>
</desc>
@@ -1055,9 +980,7 @@ handle_event(_, _, State, Data) ->
the same as
<seealso marker="#enter_loop/7"><c>enter_loop/7</c></seealso>
except that no
- <seealso marker="#type-server_name">
- <c>server_name()</c>
- </seealso>
+ <seealso marker="#type-server_name"><c>server_name()</c></seealso>
must have been registered and
<c>Actions = <anno>Server_or_Actions</anno></c>.
</p>
@@ -1095,13 +1018,9 @@ handle_event(_, _, State, Data) ->
<c><anno>Module</anno></c>, <c><anno>Opts</anno></c>, and
<c><anno>Server</anno></c> have the same meanings
as when calling
- <seealso marker="#start_link/3">
- <c>start[_link]/3,4</c>
- </seealso>.
+ <seealso marker="#start_link/3"><c>start[_link]/3,4</c></seealso>.
However, the
- <seealso marker="#type-server_name">
- <c>server_name()</c>
- </seealso>
+ <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>
@@ -1137,16 +1056,12 @@ handle_event(_, _, State, Data) ->
</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>
+ <seealso marker="#type-event_type"><c>{call,<anno>From</anno>}</c></seealso>
to the
<seealso marker="#state_function">state function</seealso>.
<c><anno>From</anno></c> and <c><anno>Reply</anno></c>
can also be specified using a
- <seealso marker="#type-reply_action">
- <c>reply_action()</c>
- </seealso>
+ <seealso marker="#type-reply_action"><c>reply_action()</c></seealso>
and multiple replies with a list of them.
</p>
<note>
@@ -1204,9 +1119,7 @@ handle_event(_, _, State, Data) ->
</p>
<p>
<c><anno>ServerName</anno></c> specifies the
- <seealso marker="#type-server_name">
- <c>server_name()</c>
- </seealso>
+ <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
@@ -1225,8 +1138,7 @@ handle_event(_, _, State, Data) ->
<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>.
+ <seealso marker="#type-start_ret"><c>{error,timeout}</c></seealso>.
</p>
</item>
<item>
@@ -1241,8 +1153,8 @@ handle_event(_, _, State, Data) ->
<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>,
+ 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>
@@ -1250,22 +1162,19 @@ handle_event(_, _, State, Data) ->
<note>
<p>
Using spawn option <c>monitor</c> is not
- allowed, it cause this function to fail with reason
+ 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>,
+ <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>,
+ <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>
@@ -1273,16 +1182,12 @@ handle_event(_, _, State, Data) ->
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>
+ <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>
+ <seealso marker="#type-start_ret"><c>{error,Reason}</c></seealso>
or
<seealso marker="#type-start_ret"><c>ignore</c></seealso>,
respectively.
@@ -1296,9 +1201,7 @@ handle_event(_, _, State, Data) ->
<desc>
<p>
The same as
- <seealso marker="#stop/3">
- <c>stop(<anno>ServerRef</anno>, normal, infinity)</c>.
- </seealso>
+ <seealso marker="#stop/3"><c>stop(<anno>ServerRef</anno>, normal, infinity)</c></seealso>.
</p>
</desc>
</func>
@@ -1309,15 +1212,11 @@ handle_event(_, _, State, Data) ->
<desc>
<p>
Orders the <c>gen_statem</c>
- <seealso marker="#type-server_ref">
- <c><anno>ServerRef</anno></c>
- </seealso>
+ <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>
+ <seealso marker="#Module:terminate/3"><c>Module:terminate/3</c></seealso>
before exiting.
</p>
<p>
@@ -1325,9 +1224,7 @@ handle_event(_, _, State, Data) ->
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:error_logger#format/2">
- <c>error_logger:format/2</c>
- </seealso>.
+ <seealso marker="kernel:error_logger#format/2"><c>error_logger:format/2</c></seealso>.
The default <c><anno>Reason</anno></c> is <c>normal</c>.
</p>
<p>
@@ -1388,9 +1285,7 @@ handle_event(_, _, State, Data) ->
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>.
+ <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
@@ -1403,9 +1298,7 @@ handle_event(_, _, State, Data) ->
<note>
<p>
If you would dare to change
- <seealso marker="#type-callback_mode">
- <em>callback mode</em>
- </seealso>
+ <seealso marker="#type-callback_mode"><em>callback mode</em></seealso>
during release upgrade/downgrade, the upgrade is no problem,
as the new code surely knows what <em>callback mode</em>
it needs. However, for a downgrade this function must
@@ -1483,8 +1376,7 @@ handle_event(_, _, State, Data) ->
return <c>{CallbackMode,State,Data}</c> or
<c>{CallbackMode,State,Data,Actions}</c>.
<c>CallbackMode</c> selects the
- <seealso marker="#type-callback_mode">
- <em>callback mode</em></seealso>
+ <seealso marker="#type-callback_mode"><em>callback mode</em></seealso>
of the <c>gen_statem</c>.
<c>State</c> is the initial
<seealso marker="#type-state"><c>state()</c></seealso>
@@ -1549,9 +1441,7 @@ handle_event(_, _, State, Data) ->
<list type="bulleted">
<item>
One of
- <seealso marker="sys#get_status/1">
- <c>sys:get_status/1,2</c>
- </seealso>
+ <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>
@@ -1564,9 +1454,7 @@ handle_event(_, _, State, Data) ->
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>
+ <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
@@ -1589,9 +1477,7 @@ handle_event(_, _, State, Data) ->
changes the 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>
+ <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",
@@ -1599,9 +1485,7 @@ handle_event(_, _, State, Data) ->
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>
+ <seealso marker="sys#get_status/1"><c>sys:get_status/1,2</c></seealso>
return value.
</p>
<p>
@@ -1642,15 +1526,11 @@ handle_event(_, _, State, Data) ->
</v>
<v>
StateFunctionResult =
- <seealso marker="#type-state_function_result">
- state_function_result()
- </seealso>
+ <seealso marker="#type-state_function_result">state_function_result()</seealso>
</v>
<v>
HandleEventResult =
- <seealso marker="#type-handle_event_result">
- handle_event_result()
- </seealso>
+ <seealso marker="#type-handle_event_result">handle_event_result()</seealso>
</v>
</type>
<desc>
@@ -1766,9 +1646,7 @@ handle_event(_, _, State, Data) ->
<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:error_logger#format/2">
- <c>error_logger:format/2</c>.
- </seealso>
+ <seealso marker="kernel:error_logger#format/2"><c>error_logger:format/2</c></seealso>.
</p>
<p>
This function can use
@@ -1781,11 +1659,13 @@ handle_event(_, _, State, Data) ->
<section>
<title>See Also</title>
- <p><seealso marker="gen_event"><c>gen_event(3)</c></seealso>,
+ <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>
+ <seealso marker="sys"><c>sys(3)</c></seealso>.
+ </p>
</section>
</erlref>
diff --git a/system/doc/design_principles/statem.xml b/system/doc/design_principles/statem.xml
index 8b0fbed7c0..585b1a35f5 100644
--- a/system/doc/design_principles/statem.xml
+++ b/system/doc/design_principles/statem.xml
@@ -84,8 +84,9 @@ State(S) x Event(E) -> Actions(A), State(S')</pre>
a server <c>Data</c> besides the state. Because of this, and as
there is no restriction on the number of states
(assuming that there is enough virtual machine memory)
- or on the number of distinct input events, makes
- a state machine implemented with this behavior Turing complete.
+ or on the number of distinct input events,
+ a state machine implemented with this behavior
+ is in fact Turing complete.
But it feels mostly like an Event-Driven Mealy Machine.
</p>
</section>
@@ -101,8 +102,8 @@ State(S) x Event(E) -> Actions(A), State(S')</pre>
<list type="bulleted">
<item>
<p>
- In mode <seealso marker="stdlib:gen_statem#type-callback_mode">
- <c>state_functions</c></seealso>,
+ In mode
+ <seealso marker="stdlib:gen_statem#type-callback_mode"><c>state_functions</c></seealso>,
the state transition rules are written as some Erlang
functions, which conform to the following convention:
</p>
@@ -113,20 +114,19 @@ StateName(EventType, EventContent, Data) ->
</item>
<item>
<p>
- In mode <seealso marker="stdlib:gen_statem#type-callback_mode">
- <c>handle_event_function</c></seealso>,
+ In mode
+ <seealso marker="stdlib:gen_statem#type-callback_mode"><c>handle_event_function</c></seealso>,
only one Erlang function provides all state transition rules:
</p>
<pre>
handle_event(EventType, EventContent, State, Data) ->
.. code for actions here ...
- {next_state, State', Data'}</pre>
+ {next_state, NewState, NewData}</pre>
</item>
</list>
<p>
Both these modes allow other return tuples; see
- <seealso marker="stdlib:gen_statem#Module:StateName/3">
- <c>Module:StateName/3</c></seealso>
+ <seealso marker="stdlib:gen_statem#Module:StateName/3"><c>Module:StateName/3</c></seealso>
in the <c>gen_statem</c> manual page.
These other return tuples can, for example, stop the machine,
execute state transition actions on the machine engine itself,
@@ -172,8 +172,7 @@ handle_event(EventType, EventContent, State, Data) ->
This mode works equally well when you want to focus on
one event at the time or on
one state at the time, but function
- <seealso marker="stdlib:gen_statem#Module:handle_event/4">
- <c>Module:handle_event/4</c></seealso>
+ <seealso marker="stdlib:gen_statem#Module:handle_event/4"><c>Module:handle_event/4</c></seealso>
quickly grows too large to handle without introducing dispatching.
</p>
<p>
@@ -291,9 +290,7 @@ start_link(Code) ->
]]></code>
<p>
<c>start_link</c> calls function
- <seealso marker="stdlib:gen_statem#start_link/4">
- <c>gen_statem:start_link/4</c>
- </seealso>,
+ <seealso marker="stdlib:gen_statem#start_link/4"><c>gen_statem:start_link/4</c></seealso>,
which spawns and links to a new process, a <c>gen_statem</c>.
</p>
<list type="bulleted">
@@ -308,9 +305,7 @@ start_link(Code) ->
Instead its pid must be used. The name can also be specified
as <c>{global,Name}</c>, then the <c>gen_statem</c> is
registered using
- <seealso marker="kernel:global#register_name/2">
- <c>global:register_name/2</c>
- </seealso>
+ <seealso marker="kernel:global#register_name/2"><c>global:register_name/2</c></seealso>
in <c>Kernel</c>.
</p>
</item>
@@ -339,9 +334,7 @@ start_link(Code) ->
<p>
The fourth argument, <c>[]</c>, is a list of options.
For the available options, see
- <seealso marker="stdlib:gen_statem#start_link/3">
- <c>gen_statem:start_link/3</c>
- </seealso>.
+ <seealso marker="stdlib:gen_statem#start_link/3"><c>gen_statem:start_link/3</c></seealso>.
</p>
</item>
</list>
@@ -350,13 +343,9 @@ start_link(Code) ->
calls callback function <c>code_lock:init(Code)</c>.
This function is expected to return <c>{CallbackMode,State,Data}</c>,
where
- <seealso marker="#callback_modes">
- <c>CallbackMode</c>
- </seealso>
+ <seealso marker="#callback_modes"><c>CallbackMode</c></seealso>
selects callback module state function mode, in this case
- <seealso marker="stdlib:gen_statem#type-callback_mode">
- <c>state_functions</c>
- </seealso>
+ <seealso marker="stdlib:gen_statem#type-callback_mode"><c>state_functions</c></seealso>
through macro <c>?CALLBACK_MODE</c>. That is, each state
has got its own handler function.
<c>State</c> is the initial state of the <c>gen_statem</c>,
@@ -375,23 +364,17 @@ init(Code) ->
{?CALLBACK_MODE,locked,Data}.
]]></code>
<p>Function
- <seealso marker="stdlib:gen_statem#start_link/3">
- <c>gen_statem:start_link</c>
- </seealso>
+ <seealso marker="stdlib:gen_statem#start_link/3"><c>gen_statem:start_link</c></seealso>
is synchronous. It does not return until the <c>gen_statem</c>
is initialized and is ready to receive events.
</p>
<p>
Function
- <seealso marker="stdlib:gen_statem#start_link/3">
- <c>gen_statem:start_link</c>
- </seealso>
+ <seealso marker="stdlib:gen_statem#start_link/3"><c>gen_statem:start_link</c></seealso>
must be used if the <c>gen_statem</c>
is part of a supervision tree, that is, started by a supervisor.
Another function,
- <seealso marker="stdlib:gen_statem#start/3">
- <c>gen_statem:start</c>
- </seealso>
+ <seealso marker="stdlib:gen_statem#start/3"><c>gen_statem:start</c></seealso>
can be used to start a standalone <c>gen_statem</c>, that is,
a <c>gen_statem</c> that is not part of a supervision tree.
</p>
@@ -403,9 +386,7 @@ init(Code) ->
<title>Handling Events</title>
<p>The function notifying the code lock about a button event is
implemented using
- <seealso marker="stdlib:gen_statem#cast/2">
- <c>gen_statem:cast/2</c>:
- </seealso>
+ <seealso marker="stdlib:gen_statem#cast/2"><c>gen_statem:cast/2</c></seealso>:
</p>
<code type="erl"><![CDATA[
button(Digit) ->
@@ -528,9 +509,7 @@ handle_event({call,From}, code_length, #{code := Code} = Data) ->
]]></code>
<p>
This example uses
- <seealso marker="stdlib:gen_statem#call/2">
- <c>gen_statem:call/2</c>
- </seealso>,
+ <seealso marker="stdlib:gen_statem#call/2"><c>gen_statem:call/2</c></seealso>,
which waits for a reply from the server.
The reply is sent with a <c>{reply,From,Reply}</c> tuple
in an action list in the <c>{keep_state,...}</c> tuple
@@ -545,15 +524,13 @@ handle_event({call,From}, code_length, #{code := Code} = Data) ->
<p>
If mode <c>handle_event_function</c> is used,
all events are handled in
- <seealso marker="stdlib:gen_statem#Module:handle_event/4">
- <c>Module:handle_event/4</c>
- </seealso>
+ <seealso marker="stdlib:gen_statem#Module:handle_event/4"><c>Module:handle_event/4</c></seealso>
and we can (but do not have to) use an event-centered approach
where we dispatch on event first and then state:
</p>
<code type="erl"><![CDATA[
...
--define(CALLBACK_MODE, state_functions).
+-define(CALLBACK_MODE, handle_event_function).
...
-export([handle_event/4]).
@@ -604,11 +581,7 @@ handle_event(timeout, _, open, Data) ->
strategy must be a time-out value and the <c>gen_statem</c> must
in function <c>init/1</c> set itself to trap exit signals
by calling
- <seealso marker="erts:erlang#process_flag/2">
- <c>process_flag(trap_exit, true)</c>
- </seealso>.
- When ordered to shut down, the <c>gen_statem</c> then calls
- callback function <c>terminate(shutdown, State, Data)</c>:
+ <seealso marker="erts:erlang#process_flag/2"><c>process_flag(trap_exit, true)</c></seealso>:
</p>
<code type="erl"><![CDATA[
init(Args) ->
@@ -617,6 +590,10 @@ init(Args) ->
...
]]></code>
<p>
+ When ordered to shut down, the <c>gen_statem</c> then calls
+ callback function <c>terminate(shutdown, State, Data)</c>.
+ </p>
+ <p>
In the following example, function <c>terminate/3</c>
locks the door if it is open, so we do not accidentally leave the door
open when the supervision tree terminates:
@@ -633,9 +610,7 @@ terminate(_Reason, State, _Data) ->
<p>
If the <c>gen_statem</c> is not part of a supervision tree,
it can be stopped using
- <seealso marker="stdlib:gen_statem#stop/1">
- <c>gen_statem:stop</c>
- </seealso>,
+ <seealso marker="stdlib:gen_statem#stop/1"><c>gen_statem:stop</c></seealso>,
preferably through an API function:
</p>
<code type="erl"><![CDATA[
@@ -660,7 +635,7 @@ stop() ->
<title>Actions</title>
<p>
In the first sections actions were mentioned as a part of
- the general state machine model. These actions
+ the general state machine model. These general actions
are implemented with the code that callback module
<c>gen_statem</c> executes in an event-handling
callback function before returning
@@ -671,17 +646,11 @@ stop() ->
that a callback function can order the <c>gen_statem</c>
engine to do after the callback function return.
These are ordered by returning a list of
- <seealso marker="stdlib:gen_statem#type-action">
- actions
- </seealso>
+ <seealso marker="stdlib:gen_statem#type-action">actions</seealso>
in the
- <seealso marker="stdlib:gen_statem#type-state_function_result">
- return tuple
- </seealso>
+ <seealso marker="stdlib:gen_statem#type-state_function_result">return tuple</seealso>
from the
- <seealso marker="stdlib:gen_statem#Module:StateName/3">
- callback function
- </seealso>.
+ <seealso marker="stdlib:gen_statem#Module:StateName/3">callback function</seealso>.
These state transition actions affect the <c>gen_statem</c>
engine itself and can do the following:
</p>
@@ -697,9 +666,7 @@ stop() ->
and replying to a caller.
An example of event postponing is included later in this chapter.
For details, see the
- <seealso marker="stdlib:gen_statem#type-action">
- <c>gen_statem(3)</c>
- </seealso>
+ <seealso marker="stdlib:gen_statem#type-action"><c>gen_statem(3)</c></seealso>
manual page.
You can, for example, reply to many callers
and generate multiple next events to handle.
@@ -712,9 +679,7 @@ stop() ->
<title>Event Types</title>
<p>
The previous sections mentioned a few
- <seealso marker="stdlib:gen_statem#type-event_type">
- event types
- </seealso>.
+ <seealso marker="stdlib:gen_statem#type-event_type">event types</seealso>.
Events of all types are handled in the same callback function,
for a given state, and the function gets
<c>EventType</c> and <c>EventContent</c> as arguments.
@@ -727,22 +692,16 @@ stop() ->
<tag><c>cast</c></tag>
<item>
Generated by
- <seealso marker="stdlib:gen_statem#cast/2">
- <c>gen_statem:cast</c>.
- </seealso>
+ <seealso marker="stdlib:gen_statem#cast/2"><c>gen_statem:cast</c></seealso>.
</item>
<tag><c>{call,From}</c></tag>
<item>
Generated by
- <seealso marker="stdlib:gen_statem#call/2">
- <c>gen_statem:call</c>
- </seealso>,
+ <seealso marker="stdlib:gen_statem#call/2"><c>gen_statem:call</c></seealso>,
where <c>From</c> is the reply address to use
when replying either through the state transition action
<c>{reply,From,Msg}</c> or by calling
- <seealso marker="stdlib:gen_statem#reply/1">
- <c>gen_statem:reply</c>
- </seealso>.
+ <seealso marker="stdlib:gen_statem#reply/1"><c>gen_statem:reply</c></seealso>.
</item>
<tag><c>info</c></tag>
<item>
@@ -759,7 +718,7 @@ stop() ->
<item>
Generated by state transition action
<c>{next_event,internal,EventContent}</c>.
- All event types above can be generated using
+ All event types above can also be generated using
<c>{next_event,EventType,EventContent}</c>.
</item>
</taglist>
@@ -780,9 +739,7 @@ stop() ->
or you want to start a timer in one state and respond
to the time-out in another. This can be accomplished
with a regular Erlang timer:
- <seealso marker="erts:erlang#start_timer/4">
- <c>erlang:start_timer</c>.
- </seealso>
+ <seealso marker="erts:erlang#start_timer/4"><c>erlang:start_timer</c></seealso>.
</p>
<p>
For the example so far in this chapter: using the
@@ -818,9 +775,7 @@ open(cast, {button,_}, Data) ->
]]></code>
<p>
If you need to cancel a timer because of some other event, you can use
- <seealso marker="erts:erlang#cancel_timer/2">
- <c>erlang:cancel_timer(Tref)</c>
- </seealso>.
+ <seealso marker="erts:erlang#cancel_timer/2"><c>erlang:cancel_timer(Tref)</c></seealso>.
Notice that a time-out message cannot arrive after this,
unless you have postponed it (see the next section) before,
so ensure that you do not accidentally postpone such messages.
@@ -844,9 +799,7 @@ open(cast, {button,_}, Data) ->
</p>
<p>
Postponing is ordered by the state transition
- <seealso marker="stdlib:gen_statem#type-action">
- action
- </seealso>
+ <seealso marker="stdlib:gen_statem#type-action">action</seealso>
<c>postpone</c>.
</p>
<p>
@@ -861,7 +814,7 @@ open(cast, {button,_}, Data) ->
...
]]></code>
<p>
- A postponed event is only retried after a state change
+ The fact that a postponed event is only retried after a state change
translates into a requirement on the event and state space.
If you have a choice between storing a state data item
in the <c>State</c> or in the <c>Data</c>:
@@ -953,9 +906,7 @@ do_unlock() ->
</p>
<p>
The state transition
- <seealso marker="stdlib:gen_statem#type-action">
- action
- </seealso>
+ <seealso marker="stdlib:gen_statem#type-action">action</seealso>
<c>postpone</c> is designed to model
selective receives. A selective receive implicitly postpones
any not received events, but the <c>postpone</c>
@@ -977,16 +928,12 @@ do_unlock() ->
It can sometimes be beneficial to be able to generate events
to your own state machine.
This can be done with the state transition
- <seealso marker="stdlib:gen_statem#type-action">
- action
- </seealso>
+ <seealso marker="stdlib:gen_statem#type-action">action</seealso>
<c>{next_event,EventType,EventContent}</c>.
</p>
<p>
You can generate events of any existing
- <seealso marker="stdlib:gen_statem#type-action">
- type
- </seealso>,
+ <seealso marker="stdlib:gen_statem#type-action">type</seealso>,
but the <c>internal</c> type can only be generated through action
<c>next_event</c>. Hence, it cannot come from an external source,
so you can be certain that an <c>internal</c> event is an event
@@ -1150,9 +1097,9 @@ code_change(_Vsn, State, Data, _Extra) ->
<p>
This section describes what to change in the example
to use one <c>handle_event/4</c> function.
- The following clean first-dispatch-on-event approach
- does not work that well because of the generated
- entry actions:
+ The previously used clean first-dispatch-on-event approach
+ does not work that well here because of the generated
+ entry actions so this example dispatches on state first:
</p>
<code type="erl"><![CDATA[
...
@@ -1227,13 +1174,9 @@ handle_event({call,From}, code_length, _State, #{code := Code}) ->
<p>
To avoid this, you can format the internal state
that gets in the error log and gets returned from
- <seealso marker="stdlib:sys#get_status/1">
- <c>sys:get_status/1,2</c>
- </seealso>
+ <seealso marker="stdlib:sys#get_status/1"><c>sys:get_status/1,2</c></seealso>
by implementing function
- <seealso marker="stdlib:gen_statem#Module:format_status/2">
- <c>Module:format_status/2</c>
- </seealso>,
+ <seealso marker="stdlib:gen_statem#Module:format_status/2"><c>Module:format_status/2</c></seealso>,
for example like this:
</p>
<code type="erl"><![CDATA[
@@ -1259,9 +1202,7 @@ format_status(Opt, [_PDict,State,Data]) ->
]]></code>
<p>
It is not mandatory to implement a
- <seealso marker="stdlib:gen_statem#Module:format_status/2">
- <c>Module:format_status/2</c>
- </seealso>
+ <seealso marker="stdlib:gen_statem#Module:format_status/2"><c>Module:format_status/2</c></seealso>
function. If you do not, a default implementation is used that
does the same as this example function without filtering
the <c>Data</c> term, that is, <c>StateData = {State,Data}</c>.
@@ -1274,13 +1215,9 @@ format_status(Opt, [_PDict,State,Data]) ->
<title>Complex State</title>
<p>
The callback mode
- <seealso marker="stdlib:gen_statem#type-callback_mode">
- <c>handle_event_function</c>
- </seealso>
+ <seealso marker="stdlib:gen_statem#type-callback_mode"><c>handle_event_function</c></seealso>
enables using a non-atom state as described in section
- <seealso marker="#callback_modes">
- Callback Modes
- </seealso>,
+ <seealso marker="#callback_modes">Callback Modes</seealso>,
for example, a complex state term like a tuple.
</p>
<p>
@@ -1308,8 +1245,7 @@ format_status(Opt, [_PDict,State,Data]) ->
<p>
So we make the <c>button/1</c> function synchronous
by using
- <seealso marker="stdlib:gen_statem#call/2">
- <c>gen_statem:call</c></seealso>
+ <seealso marker="stdlib:gen_statem#call/2"><c>gen_statem:call</c></seealso>
and still postpone its events in the <c>open</c> state.
Then a call to <c>button/1</c> during the <c>open</c>
state does not return until the state transits to <c>locked</c>,
@@ -1462,16 +1398,12 @@ format_status(Opt, [_PDict,State,Data]) ->
and the amount of heap memory all these servers need
is a problem, then the memory footprint of a server
can be mimimized by hibernating it through
- <seealso marker="stdlib:proc_lib#hibernate/3">
- <c>proc_lib:hibernate/3</c>.
- </seealso>
+ <seealso marker="stdlib:proc_lib#hibernate/3"><c>proc_lib:hibernate/3</c></seealso>.
</p>
<note>
<p>
It is rather costly to hibernate a process; see
- <seealso marker="erts:erlang#hibernate/3">
- <c>erlang:hibernate/3</c>
- </seealso>.
+ <seealso marker="erts:erlang#hibernate/3"><c>erlang:hibernate/3</c></seealso>.
It is not something you want to do after every event.
</p>
</note>
@@ -1495,9 +1427,7 @@ handle_event(
]]></code>
<p>
The
- <seealso marker="stdlib:gen_statem#type-hibernate">
- <c>[hibernate]</c>
- </seealso>
+ <seealso marker="stdlib:gen_statem#type-hibernate"><c>[hibernate]</c></seealso>
action list on the last line
when entering the <c>{open,_}</c> state is the only change.
If any event arrives in the <c>{open,_},</c> state, we