aboutsummaryrefslogtreecommitdiffstats
path: root/lib/stdlib/doc/src/gen_statem.xml
diff options
context:
space:
mode:
Diffstat (limited to 'lib/stdlib/doc/src/gen_statem.xml')
-rw-r--r--lib/stdlib/doc/src/gen_statem.xml269
1 files changed, 217 insertions, 52 deletions
diff --git a/lib/stdlib/doc/src/gen_statem.xml b/lib/stdlib/doc/src/gen_statem.xml
index 5eb13db1aa..574f488e91 100644
--- a/lib/stdlib/doc/src/gen_statem.xml
+++ b/lib/stdlib/doc/src/gen_statem.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2016-2017</year>
+ <year>2016</year><year>2017</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -62,24 +62,29 @@
</p>
</note>
<p>
- The <c>gen_statem</c> behavior is intended to replace
- <seealso marker="gen_fsm"><c>gen_fsm</c></seealso> for new code.
+ The <c>gen_statem</c> behavior replaces
+ <seealso marker="gen_fsm"><c>gen_fsm</c> </seealso> in Erlang/OTP 20.0.
It has the same features and adds some really useful:
</p>
<list type="bulleted">
- <item>State code is gathered.</item>
- <item>The state can be any term.</item>
- <item>Events can be postponed.</item>
- <item>Events can be self-generated.</item>
- <item>Automatic state enter code can be called.</item>
- <item>A reply can be sent from a later state.</item>
- <item>There can be multiple <c>sys</c> traceable replies.</item>
+ <item>Gathered 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.</item>
+ <item>Multiple <c>sys</c> traceable replies.</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 rewrite
- from <c>gen_fsm</c> to <c>gen_statem</c>.
+ 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
@@ -146,7 +151,7 @@ erlang:'!' -----> Module:StateName/3
This gathers all code for a specific state
in one function as the <c>gen_statem</c> engine
branches depending on state name.
- Notice the fact that there is a mandatory callback function
+ 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>
@@ -341,7 +346,7 @@ ok
<p>
To compare styles, here follows the same example using
<seealso marker="#type-callback_mode"><em>callback mode</em></seealso>
- <c>state_functions</c>, or rather the code to replace
+ <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>
@@ -448,6 +453,21 @@ handle_event(_, _, State, Data) ->
</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>
@@ -523,7 +543,23 @@ handle_event(_, _, State, Data) ->
<name name="event_type"/>
<desc>
<p>
- External events are of three types:
+ 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
@@ -531,10 +567,17 @@ handle_event(_, _, State, Data) ->
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>. Also, the state machine
- implementation can generate events of types
- <c>timeout</c>, <c>state_timeout</c>,
- and <c>internal</c> to itself.
+ 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>
@@ -701,13 +744,14 @@ handle_event(_, _, State, Data) ->
</item>
<item>
<p>
- Timeout timers
- <seealso marker="#type-state_timeout"><c>state_timeout()</c></seealso>
+ 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-event_timeout"><c>event_timeout()</c></seealso>
+ <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 timeout requested,
+ not yet received event so if there is such a time-out requested,
the corresponding time-out zero event is enqueued as
the newest event.
</p>
@@ -785,49 +829,102 @@ handle_event(_, _, State, Data) ->
<name name="event_timeout"/>
<desc>
<p>
- Generates an event of
+ 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>
- after this time (in milliseconds) unless another
- event arrives or has arrived
- in which case this time-out is cancelled.
+ <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 timer is requested.
+ before this time-out is requested.
</p>
<p>
- If the value is <c>infinity</c>, no timer is started, as
- it never would trigger anyway.
+ If <c>Time</c> is <c>infinity</c>,
+ no timer is started, as it never would expire anyway.
</p>
<p>
- If the value is <c>0</c> no timer is actually started,
+ 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>
- Note that it is not possible or needed to cancel this time-out,
+ 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>
- Generates an event of
+ 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>
- after this time (in milliseconds) unless the <c>gen_statem</c>
- changes states (<c>NewState =/= OldState</c>)
- which case this time-out is cancelled.
+ <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 the value is <c>infinity</c>, no timer is started, as
- it never would trigger anyway.
+ If <c>Time</c> is <c>infinity</c>,
+ no timer is started, as it never would expire anyway.
</p>
<p>
- If the value is <c>0</c> no timer is actually started,
+ 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.
@@ -840,6 +937,20 @@ handle_event(_, _, State, Data) ->
</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>
@@ -936,6 +1047,25 @@ handle_event(_, _, State, Data) ->
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>Timeout</c></tag>
<item>
<p>
@@ -945,7 +1075,6 @@ handle_event(_, _, State, Data) ->
<seealso marker="#state callback">state callback</seealso>
return value <c>{next_state,NextState,NewData,Timeout}</c>
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>
@@ -954,7 +1083,21 @@ handle_event(_, _, State, Data) ->
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>.
+ 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>
@@ -963,7 +1106,9 @@ handle_event(_, _, State, Data) ->
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>.
+ 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>
@@ -993,7 +1138,7 @@ handle_event(_, _, State, Data) ->
<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 whichcraft
+ 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.
@@ -1235,7 +1380,7 @@ handle_event(_, _, State, Data) ->
to avoid that the calling process dies when the call
times out, you will have to be prepared to handle
a late reply.
- So why not just allow the calling process to die?
+ So why not just let the calling process die?
</p>
</note>
<p>
@@ -1461,6 +1606,13 @@ handle_event(_, _, State, Data) ->
</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>
@@ -1644,6 +1796,16 @@ handle_event(_, _, State, Data) ->
<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,
@@ -1704,7 +1866,7 @@ handle_event(_, _, State, Data) ->
<func>
<name>Module:init(Args) -> Result(StateType)</name>
<fsummary>
- Optional function for initializing process and internal state.
+ Initializing process and internal state.
</fsummary>
<type>
<v>Args = term()</v>
@@ -1720,7 +1882,7 @@ handle_event(_, _, State, Data) ->
<seealso marker="#start_link/3"><c>start_link/3,4</c></seealso>
or
<seealso marker="#start/3"><c>start/3,4</c></seealso>,
- this optional function is called by the new process to initialize
+ this function is called by the new process to initialize
the implementation state and server data.
</p>
<p>
@@ -1729,13 +1891,16 @@ handle_event(_, _, State, Data) ->
</p>
<note>
<p>
- This callback is optional, so a callback module does not need
- to export it, but most do. If this function is not exported,
- the <c>gen_statem</c> should be started through
+ Note that if the <c>gen_statem</c> is started trough
<seealso marker="proc_lib"><c>proc_lib</c></seealso>
and
- <seealso marker="#enter_loop/4"><c>enter_loop/4-6</c></seealso>.
+ <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>