aboutsummaryrefslogtreecommitdiffstats
path: root/lib/stdlib
diff options
context:
space:
mode:
Diffstat (limited to 'lib/stdlib')
-rw-r--r--lib/stdlib/doc/src/gen_statem.xml203
1 files changed, 121 insertions, 82 deletions
diff --git a/lib/stdlib/doc/src/gen_statem.xml b/lib/stdlib/doc/src/gen_statem.xml
index ed44eef912..f18c1087ab 100644
--- a/lib/stdlib/doc/src/gen_statem.xml
+++ b/lib/stdlib/doc/src/gen_statem.xml
@@ -97,6 +97,9 @@ gen_statem module Callback module
gen_statem:start
gen_statem:start_link -----> Module:init/1
+Server start or code change
+ -----> Module:callback_mode/0
+
gen_statem:stop -----> Module:terminate/3
gen_statem:call
@@ -127,7 +130,8 @@ erlang:'!' -----> Module:StateName/3
in a <c>gen_statem</c> is the callback function that is called
for all events in this state. It is selected depending on which
<seealso marker="#type-callback_mode"><em>callback mode</em></seealso>
- that the implementation specifies when the server starts.
+ that the callback module defines with the callback function
+ <seealso marker="#Module:callback_mode/0"><c>Module:callback_mode/0</c></seealso>.
</p>
<p>
When the
@@ -138,9 +142,9 @@ 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 that in this mode the mandatory callback function
+ Notice the fact that there is a mandatory callback function
<seealso marker="#Module:terminate/3"><c>Module:terminate/3</c></seealso>
- makes the state name <c>terminate</c> unusable.
+ makes the state name <c>terminate</c> unusable in this mode.
</p>
<p>
When the
@@ -249,11 +253,10 @@ erlang:'!' -----> Module:StateName/3
-behaviour(gen_statem).
-export([start/0,push/0,get_count/0,stop/0]).
--export([terminate/3,code_change/4,init/1]).
+-export([terminate/3,code_change/4,init/1,callback_mode/0]).
-export([on/3,off/3]).
name() -> pushbutton_statem. % The registered server name
-callback_mode() -> state_functions.
%% API. This example uses a registered name name()
%% and does not link to the caller.
@@ -270,15 +273,14 @@ stop() ->
terminate(_Reason, _State, _Data) ->
void.
code_change(_Vsn, State, Data, _Extra) ->
- {callback_mode(),State,Data}.
+ {ok,State,Data}.
init([]) ->
- %% Set the callback mode and initial state + data.
- %% Data is used only as a counter.
+ %% Set the initial state + data. Data is used only as a counter.
State = off, Data = 0,
- {callback_mode(),State,Data}.
-
+ {ok,State,Data}.
+callback_mode() -> state_functions.
-%%% State functions
+%%% State function(s)
off({call,From}, push, Data) ->
%% Go to 'on', increment count and reply
@@ -326,18 +328,13 @@ ok
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
- from function <c>init/1</c> of the <c>pushbutton.erl</c>
+ after function <c>init/1</c> of the <c>pushbutton.erl</c>
example file above:
</p>
<code type="erl">
-init([]) ->
- %% Set the callback mode and initial state + data.
- %% Data is used only as a counter.
- State = off, Data = 0,
- {handle_event_function,State,Data}.
-
+callback_mode() -> handle_event_function.
-%%% Event handling
+%%% State function(s)
handle_event({call,From}, push, off, Data) ->
%% Go to 'on', increment count and reply
@@ -426,8 +423,8 @@ handle_event(_, _, State, Data) ->
<desc>
<p>
Debug option that can be used when starting
- a <c>gen_statem</c> server through, for example,
- <seealso marker="#enter_loop/5"><c>enter_loop/5</c></seealso>.
+ a <c>gen_statem</c> server through,
+ <seealso marker="#enter_loop/4"><c>enter_loop/4-6</c></seealso>.
</p>
<p>
For every entry in <c><anno>Dbgs</anno></c>,
@@ -525,12 +522,9 @@ handle_event(_, _, State, Data) ->
<desc>
<p>
The <em>callback mode</em> is selected when starting the
- <c>gen_statem</c> using the return value from
- <seealso marker="#Module:init/1"><c>Module:init/1</c></seealso>
- 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>.
+ <c>gen_statem</c> and after code change
+ using the return value from
+ <seealso marker="#Module:callback_mode/0"><c>Module:callback_mode/0</c></seealso>.
</p>
<taglist>
<tag><c>state_functions</c></tag>
@@ -691,7 +685,7 @@ handle_event(_, _, State, Data) ->
<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>.
+ <seealso marker="#enter_loop/5"><c>enter_loop/5,6</c></seealso>.
</p>
<p>
Actions are executed in the containing list order.
@@ -958,35 +952,36 @@ handle_event(_, _, State, Data) ->
</func>
<func>
- <name name="enter_loop" arity="5"/>
+ <name name="enter_loop" arity="4"/>
<fsummary>Enter the <c>gen_statem</c> receive loop.</fsummary>
<desc>
<p>
The same as
- <seealso marker="#enter_loop/7"><c>enter_loop/7</c></seealso>
- except that no
+ <seealso marker="#enter_loop/6"><c>enter_loop/6</c></seealso>
+ with <c>Actions = []</c> except that no
<seealso marker="#type-server_name"><c>server_name()</c></seealso>
- must have been registered.
+ must have been registered. This creates an anonymous server.
</p>
</desc>
</func>
<func>
- <name name="enter_loop" arity="6"/>
+ <name name="enter_loop" arity="5"/>
<fsummary>Enter the <c>gen_statem</c> receive loop.</fsummary>
<desc>
<p>
If <c><anno>Server_or_Actions</anno></c> is a <c>list()</c>,
the same as
- <seealso marker="#enter_loop/7"><c>enter_loop/7</c></seealso>
+ <seealso marker="#enter_loop/6"><c>enter_loop/6</c></seealso>
except that no
<seealso marker="#type-server_name"><c>server_name()</c></seealso>
must have been registered and
<c>Actions = <anno>Server_or_Actions</anno></c>.
+ This creates an anonymous server.
</p>
<p>
Otherwise the same as
- <seealso marker="#enter_loop/7"><c>enter_loop/7</c></seealso>
+ <seealso marker="#enter_loop/6"><c>enter_loop/6</c></seealso>
with
<c>Server = <anno>Server_or_Actions</anno></c> and
<c>Actions = []</c>.
@@ -995,7 +990,7 @@ handle_event(_, _, State, Data) ->
</func>
<func>
- <name name="enter_loop" arity="7"/>
+ <name name="enter_loop" arity="6"/>
<fsummary>Enter the <c>gen_statem</c> receive loop.</fsummary>
<desc>
<p>
@@ -1015,21 +1010,31 @@ handle_event(_, _, State, Data) ->
the <c>gen_statem</c> behavior provides.
</p>
<p>
- <c><anno>Module</anno></c>, <c><anno>Opts</anno></c>, and
- <c><anno>Server</anno></c> have the same meanings
- as when calling
+ <c><anno>Module</anno></c>, <c><anno>Opts</anno></c>
+ have the same meaning as when calling
<seealso marker="#start_link/3"><c>start[_link]/3,4</c></seealso>.
+ </p>
+ <p>
+ If <c><anno>Server</anno></c> is <c>self()</c> an anonymous
+ server is created just as when using
+ <seealso marker="#start_link/3"><c>start[_link]/3</c></seealso>.
+ If <c><anno>Server</anno></c> is a
+ <seealso marker="#type-server_name"><c>server_name()</c></seealso>
+ a named server is created just as when using
+ <seealso marker="#start_link/4"><c>start[_link]/4</c></seealso>.
However, the
<seealso marker="#type-server_name"><c>server_name()</c></seealso>
name must have been registered accordingly
- <em>before</em> this function is called.</p>
+ <em>before</em> this function is called.
+ </p>
<p>
- <c><anno>CallbackMode</anno></c>, <c><anno>State</anno></c>,
- <c><anno>Data</anno></c>, and <c><anno>Actions</anno></c>
+ <c><anno>State</anno></c>, <c><anno>Data</anno></c>,
+ and <c><anno>Actions</anno></c>
have the same meanings as in the return value of
<seealso marker="#Module:init/1"><c>Module:init/1</c></seealso>.
- Also, the callback module <c><anno>Module</anno></c>
- does not need to export an <c>init/1</c> function.
+ Also, the callback module does not need to export a
+ <seealso marker="#Module:init/1"><c>Module:init/1</c></seealso>
+ function.
</p>
<p>
The function fails if the calling process was not started by a
@@ -1253,6 +1258,54 @@ handle_event(_, _, State, Data) ->
<funcs>
<func>
+ <name>Module:callback_mode() -> CallbackMode</name>
+ <fsummary>Update the internal state during upgrade/downgrade.</fsummary>
+ <type>
+ <v>
+ CallbackMode =
+ <seealso marker="#type-callback_mode">callback_mode()</seealso>
+ </v>
+ </type>
+ <desc>
+ <p>
+ This function is called by a <c>gen_statem</c>
+ when it needs to find out the
+ <seealso marker="#type-callback_mode"><em>callback mode</em></seealso>
+ of the callback module. The value is cached by <c>gen_statem</c>
+ for efficiency reasons, so this function is only called
+ once after server start and after code change,
+ but before the first
+ <seealso marker="#state_function">state function</seealso>
+ is called. More occasions may be added in future versions
+ of <c>gen_statem</c>.
+ </p>
+ <p>
+ Server start happens either when
+ <seealso marker="#Module:init/1"><c>Module:init/1</c></seealso>
+ returns or when
+ <seealso marker="#enter_loop/4"><c>enter_loop/4-6</c></seealso>
+ is called. Code change happens when
+ <seealso marker="#Module:code_change/4"><c>Module:code_change/4</c></seealso>
+ returns.
+ </p>
+ <p>
+ This function can use
+ <seealso marker="erts:erlang#throw/1"><c>erlang:throw/1</c></seealso>
+ to return <c>CallbackMode</c>, just for symmetry reasons.
+ There should be no actual reason to use this.
+ </p>
+ <note>
+ <p>
+ If this function's body does not consist of solely one of two
+ possible
+ <seealso marker="#type-callback_mode">atoms</seealso>
+ the callback module is doing something strange.
+ </p>
+ </note>
+ </desc>
+ </func>
+
+ <func>
<name>Module:code_change(OldVsn, OldState, OldData, Extra) ->
Result
</name>
@@ -1262,11 +1315,7 @@ handle_event(_, _, State, Data) ->
<v>&nbsp;&nbsp;Vsn = term()</v>
<v>OldState = NewState = term()</v>
<v>Extra = term()</v>
- <v>Result = {CallbackMode,NewState,NewData} | Reason</v>
- <v>
- CallbackMode =
- <seealso marker="#type-callback_mode">callback_mode()</seealso>
- </v>
+ <v>Result = {ok,NewState,NewData} | Reason</v>
<v>
OldState = NewState =
<seealso marker="#type-state">state()</seealso>
@@ -1295,21 +1344,6 @@ handle_event(_, _, State, Data) ->
<c>Module</c>. If no such attribute is defined, the version
is the checksum of the Beam file.
</p>
- <note>
- <p>
- If you would dare to change
- <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
- know from argument <c>Extra</c> that comes from the
- <seealso marker="sasl:appup"><c>sasl:appup</c></seealso>
- file what <em>callback mode</em> the old code did use.
- It can also be possible to figure this out
- from argument <c>{down,Vsn}</c>, as <c>Vsn</c>
- in effect defines the old callback module version.
- </p>
- </note>
<p>
<c>OldState</c> and <c>OldData</c> is the internal state
of the <c>gen_statem</c>.
@@ -1321,16 +1355,16 @@ handle_event(_, _, State, Data) ->
<p>
If successful, the function must return the updated
internal state in an
- <c>{CallbackMode,NewState,NewData}</c> tuple.
+ <c>{ok,NewState,NewData}</c> tuple.
</p>
<p>
If the function returns a failure <c>Reason</c>, the ongoing
upgrade fails and rolls back to the old release.
- Note that <c>Reason</c> can not be a 3-tuple since that
- will be regarded as a
- <c>{CallbackMode,NewState,NewData}</c> tuple,
+ Note that <c>Reason</c> can not be an <c>{ok,_,_}</c> tuple
+ since that will be regarded as a
+ <c>{ok,NewState,NewData}</c> tuple,
and that a tuple matching <c>{ok,_}</c>
- is an invalid failure <c>Reason</c>.
+ is an also invalid failure <c>Reason</c>.
It is recommended to use an atom as <c>Reason</c> since
it will be wrapped in an <c>{error,Reason}</c> tuple.
</p>
@@ -1344,16 +1378,14 @@ handle_event(_, _, State, Data) ->
<func>
<name>Module:init(Args) -> Result</name>
- <fsummary>Initialize process and internal state.</fsummary>
+ <fsummary>
+ Optional function for initializing process and internal state.
+ </fsummary>
<type>
<v>Args = term()</v>
- <v>Result = {CallbackMode,State,Data}</v>
- <v>&nbsp;| {CallbackMode,State,Data,Actions}</v>
+ <v>Result = {ok,State,Data}</v>
+ <v>&nbsp;| {ok,State,Data,Actions}</v>
<v>&nbsp;| {stop,Reason} | ignore</v>
- <v>
- CallbackMode =
- <seealso marker="#type-callback_mode">callback_mode()</seealso>
- </v>
<v>State = <seealso marker="#type-state">state()</seealso></v>
<v>
Data = <seealso marker="#type-data">data()</seealso>
@@ -1372,7 +1404,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 function is called by the new process to initialize
+ this optional function is called by the new process to initialize
the implementation state and server data.
</p>
<p>
@@ -1381,11 +1413,8 @@ handle_event(_, _, State, Data) ->
</p>
<p>
If the initialization is successful, the function is to
- 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>
- of the <c>gen_statem</c>.
+ return <c>{ok,State,Data}</c> or
+ <c>{ok,State,Data,Actions}</c>.
<c>State</c> is the initial
<seealso marker="#type-state"><c>state()</c></seealso>
and <c>Data</c> the initial server
@@ -1408,6 +1437,16 @@ handle_event(_, _, State, Data) ->
<seealso marker="erts:erlang#throw/1"><c>erlang:throw/1</c></seealso>
to return <c>Result</c>.
</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
+ <seealso marker="proc_lib"><c>proc_lib</c></seealso>
+ and
+ <seealso marker="#enter_loop/4"><c>enter_loop/4-6</c></seealso>.
+ </p>
+ </note>
</desc>
</func>