aboutsummaryrefslogtreecommitdiffstats
path: root/lib/stdlib/doc
diff options
context:
space:
mode:
authorRaimo Niskanen <[email protected]>2015-10-26 11:52:17 +0100
committerRaimo Niskanen <[email protected]>2016-02-09 10:07:56 +0100
commit6ace96d3e5c9ac8ace3d8967bcafb3e6a081d9be (patch)
tree2a5dc8326bf0a52a23ac3c00de0ea365d91866e4 /lib/stdlib/doc
parentadcc726c36555434204dd0fccd13ed984741a7fb (diff)
downloadotp-6ace96d3e5c9ac8ace3d8967bcafb3e6a081d9be.tar.gz
otp-6ace96d3e5c9ac8ace3d8967bcafb3e6a081d9be.tar.bz2
otp-6ace96d3e5c9ac8ace3d8967bcafb3e6a081d9be.zip
New state machine
Diffstat (limited to 'lib/stdlib/doc')
-rw-r--r--lib/stdlib/doc/src/Makefile3
-rw-r--r--lib/stdlib/doc/src/gen_statem.xml1131
-rw-r--r--lib/stdlib/doc/src/ref_man.xml3
-rw-r--r--lib/stdlib/doc/src/specs.xml1
4 files changed, 1136 insertions, 2 deletions
diff --git a/lib/stdlib/doc/src/Makefile b/lib/stdlib/doc/src/Makefile
index 196c86748f..26602764a6 100644
--- a/lib/stdlib/doc/src/Makefile
+++ b/lib/stdlib/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2015. All Rights Reserved.
+# Copyright Ericsson AB 1997-2016. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -68,6 +68,7 @@ XML_REF3_FILES = \
gen_event.xml \
gen_fsm.xml \
gen_server.xml \
+ gen_statem.xml \
io.xml \
io_lib.xml \
lib.xml \
diff --git a/lib/stdlib/doc/src/gen_statem.xml b/lib/stdlib/doc/src/gen_statem.xml
new file mode 100644
index 0000000000..885021f61c
--- /dev/null
+++ b/lib/stdlib/doc/src/gen_statem.xml
@@ -0,0 +1,1131 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE erlref SYSTEM "erlref.dtd">
+
+<erlref>
+ <header>
+ <copyright>
+ <year>2016</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 Behaviour</modulesummary>
+ <description>
+ <p>A behaviour module for implementing a state machine, primarily
+ a finite state machine, but an infinite state space is possible.
+ A generic state machine process (gen_statem) implemented using
+ this module will have a standard set of interface functions
+ and include functionality for tracing and error reporting.
+ It will also fit into an OTP supervision tree. Refer to
+ <seealso marker="doc/design_principles:gen_server_concepts">
+ OTP Design Principles</seealso> for more information.
+ </p>
+ <p>A gen_statem assumes all specific parts to be located in a
+ callback module exporting a pre-defined set of functions.
+ The relationship between the behaviour functions and the callback
+ functions can be illustrated as follows:</p>
+ <pre>
+gen_statem module Callback module
+----------------- ---------------
+gen_statem:start
+gen_statem:start_link -----> Module:init/1
+
+gen_statem:stop -----> Module:terminate/2
+
+gen_statem:call
+gen_statem:cast
+erlang:send
+erlang:'!' -----> Module:State/5
+ Module:handle_event/5
+
+- -----> Module:terminate/3
+
+- -----> Module:code_change/3</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 gen_statem will terminate. An exception of class
+ <seealso marker="erts:erlang#throw/1"><c>throw</c></seealso>,
+ however, is not regarded as an error but as a valid return.
+ </p>
+ <marker id="state_function" />
+ <p>The "<em>state function</em>" for a specific
+ <seealso marker="#type-state">state</seealso>
+ in a gen_statem is the callback function that is called
+ for all events in this state.
+ An event can can be postponed causing it to be retried
+ after the state has changed, or more precisely;
+ after a state change all postponed events are retried
+ in the new state.
+ </p>
+ <p>The state machine
+ <seealso marker="#type-state"><c>State</c></seealso>
+ is normally an atom in which case the
+ <seealso marker="#state_function">state function</seealso>
+ that will be called is
+ <seealso marker="#Module:State/5"><c>Module:State/5</c></seealso>.
+ For a
+ <seealso marker="#type-state"><c>State</c></seealso>
+ that is <em>not</em> an atom the
+ <seealso marker="#state_function">state function</seealso>
+ <seealso marker="#Module:handle_event/5">
+ <c>Module:handle_event/5</c>
+ </seealso> will be called.
+ If you use <c>handle_event</c> as a
+ <seealso marker="#type-state">state</seealso> and later
+ decides to use non-atom states you will then have to
+ rewrite your code to stop using that state.
+ </p>
+ <p>When the using an atom-only
+ <seealso marker="#type-state">State</seealso>
+ it becomes fairly obvious in the implementation code
+ which events are handled in which state
+ since there are different callback functions for different states.
+ </p>
+ <p>
+ When using a non-atom <seealso marker="#type-state">State</seealso>
+ all events are handled in the callback function
+ <seealso marker="#Module:handle_event/5">
+ <c>Module:handle_event/5</c>
+ </seealso>
+ so it may require more coding discipline to ensure what events
+ are handled in which state. Therefore it might be a wee bit
+ easier to accidentally postpone an event in two or more states
+ and not handling it in any of them causing a tight infinite
+ loop when the event bounces to be retried between the states.
+ </p>
+ <p>A gen_statem handles system messages as documented in
+ <seealso marker="sys">sys</seealso>.
+ The <seealso marker="sys">sys</seealso> module
+ can be used for debugging a gen_statem.
+ </p>
+ <p>Note that a gen_statem does not trap exit signals automatically,
+ this must be explicitly initiated by the callback module.
+ </p>
+ <p>Unless otherwise stated, all functions in this module fail if
+ the specified gen_statem does not exist or if bad arguments are given.
+ </p>
+ <p>The gen_statem process can go into hibernation (see
+ <seealso marker="erts:erlang#hibernate/3">
+ <c>erlang:hibernate/3</c>
+ </seealso>) if a
+ <seealso marker="#state_function">state function</seealso> or
+ <seealso marker="#Module:init/1"><c>Module:init/1</c></seealso>
+ specifies <c>'hibernate'</c> in the returned
+ <seealso marker="#type-state_op"><c>StateOps</c></seealso> list.
+ This might be useful if the server is expected to be idle
+ for a long time. However use this feature with care
+ since hibernation implies at least two garbage collections
+ (when hibernating and shortly after waking up) and that is not
+ something you'd want to do between each event on a busy server.
+ </p>
+ </description>
+
+ <datatypes>
+ <datatype>
+ <name name="server_name" />
+ <desc>
+ <p>Name specification to use when starting a gen_statem 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 gen_statem server.
+ See <seealso marker="#call/2">call/2</seealso> and
+ <seealso marker="#type-server_name">
+ <c>server_name()</c>
+ </seealso> above.
+ </p>
+ <p>It can be:</p>
+ <list type="bulleted">
+ <item>the <c>pid()</c>,</item>
+ <item><c><anno>Name</anno></c>,
+ if the gen_statem is locally registered,
+ </item>
+ <item><c>{<anno>Name</anno>,<anno>Node</anno>}</c>,
+ if the gen_statem is locally registered at another node, or
+ </item>
+ <item><c>{global,<anno>GlobalName</anno>}</c>,
+ if the gen_statem is globally registered.
+ </item>
+ <item><c>{via,<anno>RegMod</anno>,<anno>ViaName</anno>}</c>,
+ if the gen_statem is registered through
+ an alternative process registry.
+ The registry callback module <c>RegMod</c>
+ should export the functions
+ <c>register_name/2</c>, <c>unregister_name/1</c>,
+ <c>whereis_name/1</c> and <c>send/2</c>,
+ which should 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>.
+ </item>
+ </list>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="debug_opt" />
+ <desc>
+ <p>Debug option that can be used when starting
+ a gen_statem server through for example
+ <seealso marker="#enter_loop/4">enter_loop/4</seealso>.
+ </p>
+ <p>For every entry in <c><anno>Dbgs</anno></c>
+ the corresponding function in
+ <seealso marker="sys"><c>sys</c></seealso> will be called.
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="start_opt" />
+ <desc>
+ <p>Options that can be used when starting
+ a gen_statem server through for example
+ <seealso marker="#start_link/3">start_link/3</seealso>.
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="start_ret" />
+ <desc>
+ <p>Return value from the start functions for_example
+ <seealso marker="#start_link/3">start_link/3</seealso>.
+ </p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="client" />
+ <desc>
+ <p>Client address to use when replying through for example the
+ <seealso marker="#type-state_op">state_op()</seealso>
+ <c>{reply,Client,Reply}</c> to a client
+ that has called the gen_statem server using
+ <seealso marker="#call/2">call/2</seealso>.
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="state" />
+ <desc>
+ <p>If the gen_statem <c>State</c> is an <c>atom()</c>, the
+ <seealso marker="#state_function">state function</seealso> is
+ <seealso marker="#Module:State/5">Module:State/5</seealso>.
+ If it is any other <c>term()</c> the
+ <seealso marker="#state_function">state function</seealso> is
+ <seealso marker="#Module:handle_event/5">
+ Module:handle_event/5
+ </seealso>. After a state change (<c>NewState =/= State</c>)
+ all postponed events are retried.
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="state_data" />
+ <desc>
+ <p>A <c>term()</c> in which the state machine implementation
+ should store any state data it needs. The difference between
+ this data and the
+ <seealso marker="#type-state">state()</seealso>
+ itself is that a change in this data does not cause
+ postponed events to be retried.
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="event_type" />
+ <desc>
+ <p>External events are of 3 different type:
+ <c>{call,<anno>Client</anno>}</c>, <c>cast</c> or <c>info</c>.
+ Calls (synchronous) and casts (asynchronous)
+ originate from the corresponding API functions.
+ For calls the event contain whom to reply to.
+ Type <c>info</c> originates from normal messages sent
+ to the gen_statem process.
+ It is also possible for the state machine
+ implementation to insert events to itself,
+ in particular of types
+ <c>timeout</c> and <c>internal</c>.
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="event_predicate" />
+ <desc>
+ <p>A <c>fun()</c> of arity 2 that takes an event
+ and returns a boolean.
+ When used in <c>{remove_event,RemoveEventPredicate}</c>
+ from <seealso marker="#type-state_op">state_op()</seealso>.
+ The event for which the predicate returns <c>true</c> will
+ be removed.
+ </p>
+ <p>
+ The predicate may <em>not</em> use a throw exception
+ to return its result.
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="state_op" />
+ <desc>
+ <p>Either a
+ <seealso marker="#type-state_option">
+ <c>state_option()</c>
+ </seealso> of which the first occurence
+ in the containing list takes precedence, or a
+ <seealso marker="#type-state_operation">
+ <c>state_operation()</c>
+ </seealso> that are performed in order of
+ the containing list.
+ </p>
+ <p>These may be returned from the
+ <seealso marker="#state_function">state function</seealso>
+ or from <seealso marker="#Module:init/1">Module:init/1</seealso>.
+ </p>
+ <p>The gen_statem enqueues postponed events and
+ not yet processed events in order of arrival, except for
+ an event that a callback function inserts with
+ <c>{insert_event,EventType,EventContent}</c> that is inserted
+ as the next event to process.
+ </p>
+ <p>When the state machine changes states all enqueued events
+ becomes not yet processed to be processed before the old
+ not yet processed events. In other words; the order of arrival
+ is retained.
+ </p>
+ <p>The processing order is:</p>
+ <list type="ordered">
+ <item>If the option <c>retry</c> is <c>true</c>
+ the current event is enqueued as postponed to be retried.
+ </item>
+ <item>If the state changes all postponed events
+ are transferred to not yet processed to be processed
+ before other not yet processed events.
+ </item>
+ <item>All operations are processed in order of appearance.
+ </item>
+ <item>The <c>timeout</c> option is processed if present.
+ So a state timer may be started or a timeout zero event
+ may be inserted as if just received.
+ </item>
+ <item>The (possibly new)
+ <seealso marker="#state_function">state function</seealso>
+ is called with the next not yet processed event
+ if there is any, otherwise the gen_statem goes into <c>receive</c>
+ or hibernation (if the option <c>hibernate</c> is <c>true</c>)
+ to wait for the next message. In hibernation the next
+ non-system event awakens the gen_statem.
+ </item>
+ </list>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="state_option" />
+ <desc>
+ <taglist>
+ <tag><c>retry</c></tag>
+ <tag><c>{retry,<anno>Retry</anno>}</c></tag>
+ <item>If <c><anno>Retry</anno> =:= true</c>
+ or plain <c>retry</c> postpone the current event
+ to be retried after a state change.
+ </item>
+ <tag><c>hibernate</c></tag>
+ <tag><c>{hibernate,<anno>Hibernate</anno>}</c></tag>
+ <item>If <c><anno>Hibernate</anno> =:= true</c>
+ or plain <c>hibernate</c> hibernate the gen_statem by calling
+ <seealso marker="proc_lib#hibernate/3">
+ <c>proc_lib:hibernate/3</c>
+ </seealso> before <c>receive</c> to wait for a new event.
+ If there are not yet processed events the
+ <c>hibernate</c> operation is ignored as if an event
+ just arrived and awakened the gen_statem.
+ </item>
+ <tag>
+ <c>{timeout,<anno>Time</anno>,<anno>Msg</anno>}</c>
+ </tag>
+ <item>Generate an event of
+ <seealso marker="#type-event_type">type <c>timeout</c></seealso>
+ after <c><anno>Time</anno></c> milliseconds unless some other
+ event is received before that time. Note that a retried
+ event counts just like a new in this respect.
+ If <c>Time =:= infinity</c> or <c>Time =:= 0</c>
+ no timer is started but for zero time the timeout
+ event is enqued as just received after all
+ other already received events.
+ Also note that it is not possible
+ to cancel this timeout using the
+ <seealso marker="#type-state_operation">
+ <c>state_operation()</c>
+ </seealso> <c>cancel_timer</c>.
+ This timeout is cancelled automatically by any event.
+ </item>
+ </taglist>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="state_operation" />
+ <desc>
+ <taglist>
+ <tag>
+ <c>{reply,<anno>Client</anno>,<anno>Reply</anno>}</c>
+ </tag>
+ <item>Reply to a client that called
+ <seealso marker="#call/2"><c>call/2</c></seealso>.
+ <c><anno>Client</anno></c> must be the term from the
+ <seealso marker="#type-event_type">
+ <c>{call,<anno>Client</anno>}</c>
+ </seealso> argument to the
+ <seealso marker="#state_function">state function</seealso>.
+ </item>
+ <tag><c>{stop,<anno>Reason</anno>}</c></tag>
+ <item>The gen_statem will call
+ <seealso marker="#Module:terminate/3">
+ <c>Module:terminate/3</c>
+ </seealso> with <c><anno>Reason</anno></c> and terminate.
+ </item>
+ <tag>
+ <c>
+ {insert_event,<anno>EventType</anno>,<anno>EventContent</anno>}
+ </c>
+ </tag>
+ <item>Insert the given event as the next to process
+ before any other not yet processed events.
+ An event of type
+ <seealso marker="#type-event_type">
+ <c>internal</c>
+ </seealso> should be used when you want to reliably distinguish
+ an event inserted this way from any external event.
+ </item>
+ <tag>
+ <c>
+ {remove_event,<anno>EventType</anno>,<anno>EventContent</anno>}
+ </c>
+ </tag>
+ <item>Remove the oldest queued event
+ that matches equal to the given event.
+ </item>
+ <tag>
+ <c>
+ {remove_event,<anno>EventPredicate</anno>}
+ </c>
+ </tag>
+ <item>Remove the oldest queued event for which
+ the <c><anno>EventPredicate</anno></c> returns <c>true</c>.
+ </item>
+ <tag><c>{cancel_timer,<anno>TimerRef</anno>}</c></tag>
+ <item>Uses <c><anno>TimerRef</anno></c> when calling
+ <seealso marker="erts:erlang#cancel_timer/2">
+ <c>erlang:cancel_timer/2</c>
+ </seealso> to cancel a timer, cleans the gen_statem's
+ message queue from any late timeout message from
+ the timer, and removes any late timeout message
+ from the queued events using
+ <c>{remove_event,<anno>EventPredicate</anno>}</c> above.
+ This is a convenience function that saves quite some
+ lines of code and testing time over doing it from
+ the primitives mentioned above.
+ </item>
+ <tag><c>{demonitor,<anno>MonitorRef</anno>}</c></tag>
+ <item>Like <c>{cancel_timer,_}</c> above but for
+ <seealso marker="erts:erlang#demonitor/2">
+ <c>demonitor/2</c>
+ </seealso>.
+ </item>
+ <tag><c>{unlink,<anno>Id</anno>}</c></tag>
+ <item>Like <c>{cancel_timer,_}</c> above but for
+ <seealso marker="erts:erlang#unlink/1">
+ <c>unlink/1</c>
+ </seealso>.
+ </item>
+ </taglist>
+ </desc>
+ </datatype>
+ </datatypes>
+
+ <funcs>
+
+ <func>
+ <name name="start_link" arity="3" />
+ <name name="start_link" arity="4" />
+ <fsummary>Create a linked gen_statem process</fsummary>
+ <desc>
+ <p>Creates a gen_statem 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 gen_statem shall be part of
+ a supervision tree so it gets linked to its supervisor.
+ </p>
+ <p>The gen_statem process calls
+ <seealso marker="#Module:init/1"><c>Module:init/1</c></seealso>
+ to initialize the server. To ensure a synchronized start-up
+ 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 gen_statem.
+ If the gen_statem is started with <c>start_link/3</c>
+ no <c><anno>ServerName</anno></c> is provided and
+ the gen_statem 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 which is passed as
+ the argument to
+ <seealso marker="#Module:init/1"><c>Module:init/1</c>
+ </seealso>.
+ </p>
+ <p>If the option <c>{timeout,Time}</c> is present in
+ <c><anno>Options</anno></c>, the gen_statem is allowed to spend
+ <c>Time</c> milliseconds initializing or it will be
+ terminated and the start function will return
+ <seealso marker="#type-start_ret">
+ <c>{error,timeout}</c>
+ </seealso>.
+ </p>
+ <p>If the option
+ <seealso marker="#type-debug_opt"><c>{debug,Dbgs}</c></seealso>
+ is present in <c><anno>Options</anno></c>, debugging through
+ <seealso marker="sys"><c>sys</c></seealso> is activated.
+ </p>
+ <p>If the option <c>{spawn_opt,SOpts}</c> is present in
+ <c><anno>Options</anno></c>, <c>SOpts</c> will be passed
+ as option list to the <c>spawn_opt</c> BIF
+ which is used to
+ <seealso marker="erts:erlang#spawn_opt/2">spawn</seealso>
+ the gen_statem.
+ </p>
+ <note>
+ <p>Using the spawn option <c>monitor</c> is currently not
+ allowed, but will cause this function to fail with reason
+ <c>badarg</c>.</p>
+ </note>
+ <p>If the gen_statem 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 gen_statem.
+ If there already exists a process with the specified
+ <c><anno>ServerName</anno></c> 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="start" arity="3" />
+ <name name="start" arity="4" />
+ <fsummary>Create a stand-alone gen_statem process</fsummary>
+ <desc>
+ <p>Creates a stand-alone gen_statem process according to
+ OTP design principles (using
+ <seealso marker="proc_lib"><c>proc_lib</c></seealso>
+ primitives).
+ Since it does not get linked to the calling process
+ this start function can not be used by a supervisor
+ to start a child.
+ </p>
+ <p>See <seealso marker="#start_link/3">start_link/3,4</seealso>
+ for a description of arguments and return values.
+ </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 gen_statem
+ <seealso marker="#type-server_ref">
+ <c><anno>ServerRef</anno></c>
+ </seealso> to exit with the given <c><anno>Reason</anno></c>
+ and waits for it to terminate.
+ The gen_statem will call
+ <seealso marker="#Module:terminate/3">
+ Module:terminate/3
+ </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> will cause an
+ error report to be issued through
+ <seealso marker="kernel:error_logger#format/2">
+ error_logger:format/2
+ </seealso>.
+ The default <c><anno>Reason</anno></c> is <c>normal</c>.
+ </p>
+ <p><c><anno>Timeout</anno></c> is an integer greater than zero
+ which specifies how many milliseconds to wait for the server to
+ terminate, or the atom <c>infinity</c> to wait indefinitely.
+ The default value is <c>infinity</c>.
+ If the server has not terminated 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>
+
+ <func>
+ <name name="call" arity="2" />
+ <name name="call" arity="3" />
+ <fsummary>Make a synchronous call to a gen_statem</fsummary>
+ <desc>
+ <p>Makes a synchronous call to the gen_statem
+ <seealso marker="#type-server_ref">
+ <c><anno>ServerRef</anno></c>
+ </seealso> by sending a request
+ and waiting until its reply arrives.
+ The gen_statem will call the
+ <seealso marker="#state_function">state function</seealso> with
+ <seealso marker="#type-event_type"><c>event_type()</c></seealso>
+ <c>{call,Client}</c> and event content
+ <c><anno>Request</anno></c>.
+ </p>
+ <p>A <c><anno>Reply</anno></c> is generated when a
+ <seealso marker="#state_function">state function</seealso>
+ returns with
+ <c>{reply,Client,<anno>Reply</anno>}</c> as one
+ <seealso marker="#type-state_op"><c>state_op()</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 greater than zero
+ 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.
+ <note>
+ <p>To avoid getting a late reply in the caller's
+ inbox 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>
+ <p>The call may fail for example if the gen_statem dies
+ before or during this function call.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="cast" arity="2" />
+ <fsummary>Send an asynchronous event to a gen_statem</fsummary>
+ <desc>
+ <p>Sends an asynchronous event to the gen_statem
+ <seealso marker="#type-server_ref">
+ <c><anno>ServerRef</anno></c>
+ </seealso> and returns <c>ok</c> immediately,
+ ignoring if the destination node or gen_statem does not exist.
+ The gen_statem will call the
+ <seealso marker="#state_function">state function</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="reply" arity="2" />
+ <fsummary>Send a reply to a client</fsummary>
+ <desc>
+ <p>This function can be used by a gen_statem to explicitly send
+ a reply to a client that called
+ <seealso marker="#call/2"><c>call/2</c></seealso>
+ when the reply cannot be defined in
+ the return value of the
+ <seealso marker="#state_function">state function</seealso>.
+ </p>
+ <p><c><anno>Client</anno></c> must be the term from the
+ <seealso marker="#type-event_type">
+ <c>{call,<anno>Client</anno>}</c>
+ </seealso> argument to the
+ <seealso marker="#state_function">state function</seealso>.
+ </p>
+ <note>
+ <p>A reply sent with this function will not be visible
+ in <seealso marker="sys">sys</seealso> debug output.
+ </p>
+ </note>
+ </desc>
+ </func>
+
+ <func>
+ <name name="enter_loop" arity="4" />
+ <fsummary>Enter the gen_statem receive loop</fsummary>
+ <desc>
+ <p>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.
+ </p>
+ </desc>
+ </func>
+ <func>
+ <name name="enter_loop" arity="5" />
+ <fsummary>Enter the gen_statem receive loop</fsummary>
+ <desc>
+ <p>If <c><anno>Server_or_StateOps</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>StateOps = <anno>Server_or_StateOps</anno></c>.
+ </p>
+ <p>Otherwise the same as
+ <seealso marker="#enter_loop/6"><c>enter_loop/6</c></seealso>
+ with
+ <c>Server = <anno>Server_or_StateOps</anno></c> and
+ <c>StateOps = []</c>.
+ </p>
+ </desc>
+ </func>
+ <func>
+ <name name="enter_loop" arity="6" />
+ <fsummary>Enter the gen_statem receive loop</fsummary>
+ <desc>
+ <p>Makes an the calling process become a gen_statem. Does not return,
+ instead the calling process will enter the gen_statem receive
+ loop and become a gen_statem 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 gen_statem behaviour provides.
+ </p>
+ <p><c><anno>Module</anno></c>, <c><anno>Options</anno></c> and
+ <c><anno>Server</anno></c> have the same meanings
+ as when calling
+ <seealso marker="#start_link/3">gen_statem:start[_link]/3,4</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> and <c><anno>StateData</anno></c>
+ have the same meanings as in the return value of
+ <seealso marker="#Module:init/1">Module:init/1</seealso>.
+ Also, the callback module <c><anno>Module</anno></c>
+ does not need to export an <c>init/1</c> function.
+ </p>
+ <p>Failure: 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>
+
+ </funcs>
+
+
+
+ <section>
+ <title>CALLBACK FUNCTIONS</title>
+ <p>The following functions should be exported from a
+ <c>gen_statem</c> callback module.
+ </p>
+ </section>
+ <funcs>
+
+ <func>
+ <name>Module:init(Args) -> Result</name>
+ <fsummary>Initialize process and internal state</fsummary>
+ <type>
+ <v>Args = term()</v>
+ <v>Result = {ok,State,StateData}</v>
+ <v>&nbsp;| {ok,State,StateData,StateOps}</v>
+ <v>&nbsp;| {stop,Reason} | ignore</v>
+ <v>State = <seealso marker="#type-state">state()</seealso></v>
+ <v>StateData = <seealso marker="#type-state_data">state_data()</seealso></v>
+ <v>StateOps = [<seealso marker="#type-state_op">state_op()</seealso>]</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <marker id="Module:init-1" />
+ <p>Whenever a gen_statem is started using
+ <seealso marker="#start_link/3">gen_statem:start_link/3,4</seealso>
+ or
+ <seealso marker="#start/3">gen_statem:start/3,4</seealso>,
+ this function is called by the new process to initialize
+ the implementation loop data.
+ </p>
+ <p><c>Args</c> is the <c>Args</c> argument provided to the start
+ function.</p>
+ <p>If the initialization is successful, the function should
+ return <c>{ok,State,StateData}</c> or
+ <c>{ok,State,StateData,StateOps}</c>.
+ <c>State</c> is the <seealso marker="#type-state">state</seealso>
+ of the gen_statem.
+ </p>
+ <p>The <seealso marker="#type-state_op"><c>StateOps</c></seealso>
+ are executed before entering the first
+ <seealso marker="#type-state">state</seealso> just as for a
+ <seealso marker="#state_function">state function</seealso>.
+ </p>
+ <p>If something goes wrong during the initialization
+ the function should return <c>{stop,Reason}</c>
+ or <c>ignore</c>. See
+ <seealso marker="#start_link/3">gen_statem:start_link/3,4</seealso>.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>Module:handle_event(EventType, EventContent,
+ PrevState, State, StateData) -> Result
+ </name>
+ <name>Module:State(EventType, EventContent,
+ PrevState, State, StateData) -> Result
+ </name>
+ <fsummary>Handle an event</fsummary>
+ <type>
+ <v>EventType =
+ <seealso marker="#type-event_type">event_type()</seealso>
+ </v>
+ <v>EventContent = term()</v>
+ <v>Result = {NewState,NewStateData,StateOps}</v>
+ <v>&nbsp;&nbsp;| {NewState,NewStateData}</v>
+ <d>&nbsp;&nbsp;The same as <c>{NewState,NewStateData,[]}</c></d>
+ <v>&nbsp;&nbsp;| {NewStateData}</v>
+ <d>&nbsp;&nbsp;The same as <c>{State,NewStateData,[retry]}</c></d>
+ <v>&nbsp;&nbsp;| {}</v>
+ <d>&nbsp;&nbsp;The same as <c>{State,StateData,[]}</c></d>
+ <v>&nbsp;&nbsp;| StateOps</v>
+ <d>&nbsp;&nbsp;The same as <c>{State,StateData,StateOps}</c></d>
+
+ <v>PrevState = State = NewState =
+ <seealso marker="#type-state">state()</seealso>
+ </v>
+ <v>StateData = NewStateData =
+ <seealso marker="#type-state_data">state_data()</seealso>
+ </v>
+ <v>StateOps =
+ [<seealso marker="#type-state_op">state_op()</seealso>]
+ </v>
+ </type>
+ <desc>
+ <p>Whenever a gen_statem receives an event from
+ <seealso marker="#call/2">gen_statem:call/2</seealso>,
+ <seealso marker="#cast/2">gen_statem:cast/2</seealso> or
+ as a normal process message this function is called.
+ If the <c>EventType</c> is
+ <seealso marker="#type-event_type"><c>{call,Client}</c></seealso>
+ the client is waiting for a reply. The reply can be sent
+ from this or from any other
+ <seealso marker="#state_function">state function</seealso>
+ by returning with <c>{reply,Client,Reply}</c> in
+ <seealso marker="#type-state_op">StateOps</seealso>
+ or by calling
+ <seealso marker="#reply/2">
+ <c>gen_statem:reply(Client, Reply)</c>
+ </seealso>.
+ </p>
+ <p><seealso marker="#type-state"><c>State</c></seealso>
+ is the internal state of the gen_statem which
+ when <c>State</c> is an <c>atom()</c>
+ is the same as this function's name, so it is seldom useful,
+ except for example when comparing with <c>PrevState</c>
+ that is the gen_statem's previous state, or in
+ <seealso marker="#Module:handle_event/5">
+ Module:handle_event/5
+ </seealso> since that function is common for all states
+ that are not an <c>atom()</c>.
+ </p>
+ <p>If this function returns with
+ <seealso marker="#type-state"><c>NewState =/= State</c></seealso>
+ all postponed events will be retried in the new state.
+ </p>
+ <p>See <seealso marker="#type-state_op">state_op()</seealso>
+ for the operations that can be done by gen_statem
+ after returning from this function.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>Module:terminate(Reason, State, StateData)</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>StateData =
+ <seealso marker="#type-state_data">
+ state_data()
+ </seealso>
+ </v>
+ </type>
+ <desc>
+ <p>This function is called by a gen_statem when it is about to
+ terminate. It should 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 gen_statem 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">State</seealso>
+ is the internal state of the gen_statem.
+ </p>
+ <p><c>Reason</c> depends on why the gen_statem is terminating.
+ If it is because another callback function has returned a
+ stop tuple <c>{stop,Reason}</c> in
+ <seealso marker="#type-state_op">StateOps</seealso>,
+ <c>Reason</c> will have the value specified in that tuple.
+ If it is due to a failure, <c>Reason</c> is the error reason.
+ </p>
+ <p>If the gen_statem is part of a supervision tree and is
+ ordered by its supervisor to terminate, this function will be
+ called with <c>Reason = shutdown</c> if the following
+ conditions apply:</p>
+ <list type="bulleted">
+ <item>the gen_statem has been set to trap exit signals, and</item>
+ <item>the shutdown strategy as defined in the supervisor's
+ child specification is an integer timeout value, not
+ <c>brutal_kill</c>.
+ </item>
+ </list>
+ <p>Even if the gen_statem is <em>not</em> part of a supervision tree,
+ this function will be called if it receives an <c>'EXIT'</c>
+ message from its parent. <c>Reason</c> will be the same as in
+ the <c>'EXIT'</c> message.
+ </p>
+ <p>Otherwise, the gen_statem will be immediately terminated.
+ </p>
+ <p>Note that for any other reason than <c>normal</c>,
+ <c>shutdown</c>, or <c>{shutdown,Term}</c> the gen_statem is
+ assumed to terminate due to an error and
+ an error report is issued using
+ <seealso marker="kernel:error_logger#format/2">
+ error_logger:format/2
+ </seealso>.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>Module:code_change(OldVsn, OldState, OldStateData, Extra) ->
+ Result
+ </name>
+ <fsummary>Update the internal state during upgrade/downgrade</fsummary>
+ <type>
+ <v>OldVsn = Vsn | {down,Vsn}</v>
+ <v>&nbsp;&nbsp;Vsn = term()</v>
+ <v>OldState = NewState = term()</v>
+ <v>Extra = term()</v>
+ <v>Result = {ok,{NewState,NewStateData}} | Reason</v>
+ <v>OldState = NewState =
+ <seealso marker="#type-state">state()</seealso>
+ </v>
+ <v>OldStateData = NewStateData =
+ <seealso marker="#type-state_data">state_data()</seealso>
+ </v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>This function is called by a gen_statem when it should
+ update its internal state during a release upgrade/downgrade,
+ i.e. when the instruction <c>{update,Module,Change,...}</c>
+ where <c>Change={advanced,Extra}</c> is given in
+ the <c>appup</c> file. See
+ <seealso marker="doc/design_principles:release_handling#instr">
+ OTP Design Principles
+ </seealso>
+ for more information.
+ </p>
+ <p>In the case of an upgrade, <c>OldVsn</c> is <c>Vsn</c>, and
+ in the case of 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>OldStateData</c> is the internal state
+ of the gen_statem.
+ </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 shall return the updated
+ internal state in an
+ <c>{ok,{NewState,NewStateData}}</c> tuple.
+ </p>
+ <p>If the function returns <c>Reason</c>, the ongoing
+ upgrade will fail and roll back to the old release.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>Module:format_status(Opt, [PDict,State,StateData]) ->
+ Status
+ </name>
+ <fsummary>Optional function for providing a term describing the
+ current gen_statem status</fsummary>
+ <type>
+ <v>Opt = normal | terminate</v>
+ <v>PDict = [{Key, Value}]</v>
+ <v>State =
+ <seealso marker="#type-state">state()</seealso>
+ </v>
+ <v>StateData =
+ <seealso marker="#type-state_data">state_data()</seealso>
+ </v>
+ <v>Key = term()</v>
+ <v>Value = term()</v>
+ <v>Status = term()</v>
+ </type>
+ <desc>
+ <note>
+ <p>This callback is optional, so callback modules need not
+ export it. The gen_statem module provides a default
+ implementation of this function that returns the callback
+ module state.
+ </p>
+ </note>
+ <p>This function is called by a gen_statem process when:</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 gen_statem status. <c>Opt</c> is set
+ to the atom <c>normal</c> for this case.
+ </item>
+ <item>The gen_statem 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 customising the form and
+ appearance of the gen_statem status for these cases. A
+ callback module wishing to customise the
+ <seealso marker="sys#get_status/1">
+ <c>sys:get_status/1,2</c>
+ </seealso> return value as well as how
+ its status appears in termination error logs exports an
+ instance of <c>format_status/2</c> that returns a term
+ describing the current status of the gen_statem.
+ </p>
+ <p><c>PDict</c> is the current value of the gen_statem's
+ process dictionary.
+ </p>
+ <p><seealso marker="#type-state"><c>State</c></seealso>
+ is the internal state of the gen_statem.
+ </p>
+ <p>The function should return <c>Status</c>, a term that
+ customises the details of the current state and status of
+ the gen_statem. 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 gen_statem state. Following this recommendation isn't
+ required, but doing so will make 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 logfiles.
+ </p>
+ </desc>
+ </func>
+
+ </funcs>
+
+ <section>
+ <title>SEE ALSO</title>
+ <p><seealso marker="gen_event">gen_event</seealso>,
+ <seealso marker="gen_fsm">gen_fsm</seealso>,
+ <seealso marker="gen_server">gen_server</seealso>,
+ <seealso marker="supervisor">supervisor</seealso>,
+ <seealso marker="proc_lib">proc_lib</seealso>,
+ <seealso marker="sys">sys</seealso></p>
+ </section>
+</erlref>
diff --git a/lib/stdlib/doc/src/ref_man.xml b/lib/stdlib/doc/src/ref_man.xml
index 82ad78e675..404873ea32 100644
--- a/lib/stdlib/doc/src/ref_man.xml
+++ b/lib/stdlib/doc/src/ref_man.xml
@@ -4,7 +4,7 @@
<application xmlns:xi="http://www.w3.org/2001/XInclude">
<header>
<copyright>
- <year>1996</year><year>2015</year>
+ <year>1996</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -66,6 +66,7 @@
<xi:include href="gen_event.xml"/>
<xi:include href="gen_fsm.xml"/>
<xi:include href="gen_server.xml"/>
+ <xi:include href="gen_statem.xml"/>
<xi:include href="io.xml"/>
<xi:include href="io_lib.xml"/>
<xi:include href="lib.xml"/>
diff --git a/lib/stdlib/doc/src/specs.xml b/lib/stdlib/doc/src/specs.xml
index 0418bf7b22..45b207b13d 100644
--- a/lib/stdlib/doc/src/specs.xml
+++ b/lib/stdlib/doc/src/specs.xml
@@ -30,6 +30,7 @@
<xi:include href="../specs/specs_gen_event.xml"/>
<xi:include href="../specs/specs_gen_fsm.xml"/>
<xi:include href="../specs/specs_gen_server.xml"/>
+ <xi:include href="../specs/specs_gen_statem.xml"/>
<xi:include href="../specs/specs_io.xml"/>
<xi:include href="../specs/specs_io_lib.xml"/>
<xi:include href="../specs/specs_lib.xml"/>