aboutsummaryrefslogtreecommitdiffstats
path: root/lib/stdlib
diff options
context:
space:
mode:
Diffstat (limited to 'lib/stdlib')
-rw-r--r--lib/stdlib/doc/src/gen_statem.xml87
-rw-r--r--lib/stdlib/doc/src/proc_lib.xml8
-rw-r--r--lib/stdlib/doc/src/supervisor.xml10
-rw-r--r--lib/stdlib/doc/src/sys.xml31
-rw-r--r--lib/stdlib/src/gen_statem.erl93
5 files changed, 153 insertions, 76 deletions
diff --git a/lib/stdlib/doc/src/gen_statem.xml b/lib/stdlib/doc/src/gen_statem.xml
index 01be3099c1..db6a4e03ea 100644
--- a/lib/stdlib/doc/src/gen_statem.xml
+++ b/lib/stdlib/doc/src/gen_statem.xml
@@ -407,7 +407,7 @@ ok
<name name="state" />
<desc>
<p>
- After a state change (<c>NewState =/= State</c>)
+ After a state change (<c>NextState =/= State</c>)
all postponed events are retried.
</p>
</desc>
@@ -566,7 +566,7 @@ ok
<p>
If <c>true</c> postpone the current event and retry
it when the state changes that is:
- <c>NewState =/= State</c>.
+ <c>NextState =/= State</c>.
</p>
</desc>
</datatype>
@@ -701,7 +701,47 @@ ok
</desc>
</datatype>
<datatype>
- <name name="state_callback_result" />
+ <name name="state_function_result" />
+ <desc>
+ <taglist>
+ <tag><c>next_state</c></tag>
+ <item>
+ The <c>gen_statem</c> will do a state transition to
+ <c><anno>NextStateName</anno></c>
+ (which may be the same as the current state),
+ set <c><anno>NewData</anno></c>
+ and execute all <c><anno>Actions</anno></c>
+ </item>
+ </taglist>
+ <p>
+ All these terms are tuples or atoms and this property
+ will hold in any future version of <c>gen_statem</c>,
+ just in case you need such a promise.
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="handle_event_result" />
+ <desc>
+ <taglist>
+ <tag><c>next_state</c></tag>
+ <item>
+ The <c>gen_statem</c> will do a state transition to
+ <c><anno>NextState</anno></c>
+ (which may be the same as the current state),
+ set <c><anno>NewData</anno></c>
+ and execute all <c><anno>Actions</anno></c>
+ </item>
+ </taglist>
+ <p>
+ All these terms are tuples or atoms and this property
+ will hold in any future version of <c>gen_statem</c>,
+ just in case you need such a promise.
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="common_state_callback_result" />
<desc>
<taglist>
<tag><c>stop</c></tag>
@@ -723,14 +763,6 @@ ok
with <c>Reason</c> and
<c><anno>NewData</anno></c>, if given.
</item>
- <tag><c>next_state</c></tag>
- <item>
- The <c>gen_statem</c> will do a state transition to
- <c><anno>NewState</anno></c>
- (which may be the same as the current state),
- set <c><anno>NewData</anno></c>
- and execute all <c><anno>Actions</anno></c>
- </item>
<tag><c>keep_state</c></tag>
<item>
The <c>gen_statem</c> will keep the current state, or
@@ -1209,10 +1241,11 @@ ok
</func>
<func>
- <name>Module:StateName(EventType, EventContent, Data) -> Result
+ <name>Module:StateName(EventType, EventContent, Data) ->
+ StateFunctionResult
</name>
<name>Module:handle_event(EventType, EventContent,
- State, Data) -> Result
+ State, Data) -> HandleEventResult
</name>
<fsummary>Handle an event</fsummary>
<type>
@@ -1222,7 +1255,7 @@ ok
</v>
<v>EventContent = term()</v>
<v>
- State = NewState =
+ State =
<seealso marker="#type-state">state()</seealso>
</v>
<v>
@@ -1230,9 +1263,15 @@ ok
<seealso marker="#type-data">data()</seealso>
</v>
<v>
- Result =
- <seealso marker="#type-state_callback_result">
- state_callback_result()
+ StateFunctionResult =
+ <seealso marker="#type-state_function_result">
+ state_function_result()
+ </seealso>
+ </v>
+ <v>
+ HandleEventResult =
+ <seealso marker="#type-handle_event_result">
+ handle_event_result()
</seealso>
</v>
</type>
@@ -1260,9 +1299,15 @@ ok
<seealso marker="#reply/2"><c>reply(Caller, Reply)</c></seealso>.
</p>
<p>
- If this function returns with a new state that
+ If this function returns with a next state that
does not match equal (<c>=/=</c>) to the current state
- all postponed events will be retried in the new state.
+ all postponed events will be retried in the next state.
+ </p>
+ <p>
+ The only difference between <c>StateFunctionResult</c> and
+ <c>HandleEventResult</c> is that for <c>StateFunctionResult</c>
+ the next state has to be an atom but for <c>HandleEventResult</c>
+ there is no restriction on the next state.
</p>
<p>
See <seealso marker="#type-action">action()</seealso>
@@ -1272,7 +1317,7 @@ ok
<p>
These functions may use
<seealso marker="erts:erlang#throw/1"><c>throw</c></seealso>,
- to return <c>Result</c>.
+ to return the result.
</p>
</desc>
</func>
@@ -1401,7 +1446,7 @@ ok
<p>
If successful, the function shall return the updated
internal state in an
- <c>{ok,{NewState,NewData}}</c> tuple.
+ <c>{ok,NewState,NewData}</c> tuple.
</p>
<p>
If the function returns <c>Reason</c>, the ongoing
diff --git a/lib/stdlib/doc/src/proc_lib.xml b/lib/stdlib/doc/src/proc_lib.xml
index 85f0c0c908..245580b1ba 100644
--- a/lib/stdlib/doc/src/proc_lib.xml
+++ b/lib/stdlib/doc/src/proc_lib.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2014</year>
+ <year>1996</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -34,9 +34,9 @@
<p>This module is used to start processes adhering to
the <seealso marker="doc/design_principles:des_princ">OTP Design Principles</seealso>. Specifically, the functions in this
module are used by the OTP standard behaviors (<c>gen_server</c>,
- <c>gen_fsm</c>, ...) when starting new processes. The functions
- can also be used to start <em>special processes</em>, user
- defined processes which comply to the OTP design principles. See
+ <c>gen_fsm</c>, <c>gen_statem</c>, ...) when starting new processes.
+ The functions can also be used to start <em>special processes</em>,
+ user defined processes which comply to the OTP design principles. See
<seealso marker="doc/design_principles:spec_proc">Sys and Proc_Lib</seealso> in OTP Design Principles for an example.</p>
<p>Some useful information is initialized when a process starts.
The registered names, or the process identifiers, of the parent
diff --git a/lib/stdlib/doc/src/supervisor.xml b/lib/stdlib/doc/src/supervisor.xml
index 24ff251ce3..9d81fb0db7 100644
--- a/lib/stdlib/doc/src/supervisor.xml
+++ b/lib/stdlib/doc/src/supervisor.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2014</year>
+ <year>1996</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -34,8 +34,8 @@
<p>A behaviour module for implementing a supervisor, a process which
supervises other processes called child processes. A child
process can either be another supervisor or a worker process.
- Worker processes are normally implemented using one of
- the <c>gen_event</c>, <c>gen_fsm</c>, or <c>gen_server</c>
+ Worker processes are normally implemented using one of the
+ <c>gen_event</c>, <c>gen_fsm</c>, <c>gen_statem</c> or <c>gen_server</c>
behaviours. A supervisor implemented using this module will have
a standard set of interface functions and include functionality
for tracing and error reporting. Supervisors are used to build a
@@ -221,7 +221,8 @@
<p><c>modules</c> is used by the release handler during code
replacement to determine which processes are using a certain
module. As a rule of thumb, if the child process is a
- <c>supervisor</c>, <c>gen_server</c>, or <c>gen_fsm</c>,
+ <c>supervisor</c>, <c>gen_server</c>,
+ <c>gen_fsm</c> or <c>gen_statem</c>
this should be a list with one element <c>[Module]</c>,
where <c>Module</c> is the callback module. If the child
process is an event manager (<c>gen_event</c>) with a
@@ -633,6 +634,7 @@
<title>SEE ALSO</title>
<p><seealso marker="gen_event">gen_event(3)</seealso>,
<seealso marker="gen_fsm">gen_fsm(3)</seealso>,
+ <seealso marker="gen_statem">gen_statem(3)</seealso>,
<seealso marker="gen_server">gen_server(3)</seealso>,
<seealso marker="sys">sys(3)</seealso></p>
</section>
diff --git a/lib/stdlib/doc/src/sys.xml b/lib/stdlib/doc/src/sys.xml
index d400f72e1d..2255395f46 100644
--- a/lib/stdlib/doc/src/sys.xml
+++ b/lib/stdlib/doc/src/sys.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2014</year>
+ <year>1996</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -217,14 +217,18 @@
processes. For example, a <c>gen_server</c> process returns
the callback module's state, a <c>gen_fsm</c> process
returns information such as its current state name and state data,
- and a <c>gen_event</c> process returns information about each of its
+ a <c>gen_statem</c> process returns information about
+ its current state and data, and a <c>gen_event</c> process
+ returns information about each of its
registered handlers. Callback modules for <c>gen_server</c>,
- <c>gen_fsm</c>, and <c>gen_event</c> can also customise the value
+ <c>gen_fsm</c>, <c>gen_statem</c> and <c>gen_event</c>
+ can also customise the value
of <c><anno>Misc</anno></c> by exporting a <c>format_status/2</c>
function that contributes module-specific information;
- see <seealso marker="gen_server#Module:format_status/2">gen_server:format_status/2</seealso>,
- <seealso marker="gen_fsm#Module:format_status/2">gen_fsm:format_status/2</seealso>, and
- <seealso marker="gen_event#Module:format_status/2">gen_event:format_status/2</seealso>
+ see <seealso marker="gen_server#Module:format_status/2">gen_server format_status/2</seealso>,
+ <seealso marker="gen_fsm#Module:format_status/2">gen_fsm format_status/2</seealso>,
+ <seealso marker="gen_statem#Module:format_status/2">gen_statem format_status/2</seealso>, and
+ <seealso marker="gen_event#Module:format_status/2">gen_event format_status/2</seealso>
for more details.</p>
</desc>
</func>
@@ -245,6 +249,8 @@
processes. For a <c>gen_server</c> process, the returned <c><anno>State</anno></c>
is simply the callback module's state. For a <c>gen_fsm</c> process,
<c><anno>State</anno></c> is the tuple <c>{CurrentStateName, CurrentStateData}</c>.
+ For a <c>gen_statem</c> process <c><anno>State</anno></c> is
+ the tuple <c>{CurrentState,CurrentData}.</c>
For a <c>gen_event</c> process, <c><anno>State</anno></c> a list of tuples,
where each tuple corresponds to an event handler registered in the process and contains
<c>{Module, Id, HandlerState}</c>, where <c>Module</c> is the event handler's module name,
@@ -263,8 +269,9 @@
details of the exception.</p>
<p>The <c>system_get_state/1</c> function is primarily useful for user-defined
behaviours and modules that implement OTP <seealso marker="#special_process">special
- processes</seealso>. The <c>gen_server</c>, <c>gen_fsm</c>, and <c>gen_event</c> OTP
- behaviour modules export this function, and so callback modules for those behaviours
+ processes</seealso>. The <c>gen_server</c>, <c>gen_fsm</c>,
+ <c>gen_statem</c> and <c>gen_event</c> OTP
+ behaviour modules export this function, so callback modules for those behaviours
need not supply their own.</p>
<p>To obtain more information about a process, including its state, see
<seealso marker="#get_status-1">get_status/1</seealso> and
@@ -290,6 +297,8 @@
<c>gen_fsm</c> process, <c><anno>State</anno></c> is the tuple
<c>{CurrentStateName, CurrentStateData}</c>, and <c><anno>NewState</anno></c>
is a similar tuple that may contain a new state name, new state data, or both.
+ The same applies for a <c>gen_statem</c> process but
+ it names the tuple fields <c>{CurrentState,CurrentData}</c>.
For a <c>gen_event</c> process, <c><anno>State</anno></c> is the tuple
<c>{Module, Id, HandlerState}</c> where <c>Module</c> is the event handler's module name,
<c>Id</c> is the handler's ID (which is the value <c>false</c> if it was registered without
@@ -304,7 +313,8 @@
state, then regardless of process type, it may simply return its <c><anno>State</anno></c>
argument.</p>
<p>If a <c><anno>StateFun</anno></c> function crashes or throws an exception, then
- for <c>gen_server</c> and <c>gen_fsm</c> processes, the original state of the process is
+ for <c>gen_server</c>, <c>gen_fsm</c> or <c>gen_statem</c> processes,
+ the original state of the process is
unchanged. For <c>gen_event</c> processes, a crashing or failing <c><anno>StateFun</anno></c>
function means that only the state of the particular event handler it was working on when it
failed or crashed is unchanged; it can still succeed in changing the states of other event
@@ -329,7 +339,8 @@
<c>{callback_failed, StateFun, {Class, Reason}}</c>.</p>
<p>The <c>system_replace_state/2</c> function is primarily useful for user-defined behaviours and
modules that implement OTP <seealso marker="#special_process">special processes</seealso>. The
- <c>gen_server</c>, <c>gen_fsm</c>, and <c>gen_event</c> OTP behaviour modules export this function,
+ <c>gen_server</c>, <c>gen_fsm</c>, <c>gen_statem</c> and
+ <c>gen_event</c> OTP behaviour modules export this function,
and so callback modules for those behaviours need not supply their own.</p>
</desc>
</func>
diff --git a/lib/stdlib/src/gen_statem.erl b/lib/stdlib/src/gen_statem.erl
index cc09efc140..438c366f8e 100644
--- a/lib/stdlib/src/gen_statem.erl
+++ b/lib/stdlib/src/gen_statem.erl
@@ -44,8 +44,16 @@
-export(
[wakeup_from_hibernate/3]).
+%% Type exports for templates
+-export_type(
+ [event_type/0,
+ callback_mode/0,
+ state_function_result/0,
+ handle_event_result/0,
+ action/0]).
+
%% Fix problem for doc build
--export_type([transition_option/0,state_callback_result/0]).
+-export_type([transition_option/0]).
%%%==========================================================================
%%% Interface functions.
@@ -84,7 +92,7 @@
-type action() ::
%% During a state change:
- %% * NewState and NewData are set.
+ %% * NextState and NewData are set.
%% * All action()s are executed in order of apperance.
%% * Postponing the current event is performed
%% iff 'postpone' is 'true'.
@@ -119,7 +127,25 @@
{'reply', % Reply to a caller
Caller :: caller(), Reply :: term()}.
--type state_callback_result() ::
+-type state_function_result() ::
+ {'next_state', % {next_state,NextStateName,NewData,[]}
+ NextStateName :: state_name(),
+ NewData :: data()} |
+ {'next_state', % State transition, maybe to the same state
+ NextStateName :: state_name(),
+ NewData :: data(),
+ Actions :: [action()] | action()} |
+ common_state_callback_result().
+-type handle_event_result() ::
+ {'next_state', % {next_state,NextState,NewData,[]}
+ NextState :: state(),
+ NewData :: data()} |
+ {'next_state', % State transition, maybe to the same state
+ NextState :: state(),
+ NewData :: data(),
+ Actions :: [action()] | action()} |
+ common_state_callback_result().
+-type common_state_callback_result() ::
'stop' | % {stop,normal}
{'stop', % Stop the server
Reason :: term()} |
@@ -133,13 +159,6 @@
Reason :: term(),
Replies :: [reply_action()] | reply_action(),
NewData :: data()} |
- {'next_state', % {next_state,NewState,NewData,[]}
- NewState :: state(),
- NewData :: data()} |
- {'next_state', % State transition, maybe to the same state
- NewState :: state(),
- NewData :: data(),
- Actions :: [action()] | action()} |
{'keep_state', % {keep_state,NewData,[]}
NewData :: data()} |
{'keep_state', % Keep state, change data
@@ -171,7 +190,7 @@
event_type(),
EventContent :: term(),
Data :: data()) ->
- state_callback_result().
+ state_function_result().
%%
%% State callback for callback_mode() =:= handle_event_function.
%%
@@ -182,7 +201,7 @@
EventContent :: term(),
State :: state(), % Current state
Data :: data()) ->
- state_callback_result().
+ handle_event_result().
%% Clean up before the server terminates.
-callback terminate(
@@ -514,7 +533,7 @@ enter(Module, Opts, CallbackMode, State, Data, Server, Actions, Parent) ->
%% The values should already have been type checked
Name = gen:get_proc_name(Server),
Debug = gen:debug_options(Name, Opts),
- OldState = make_ref(), % Will be discarded by loop_event_actions/9
+ PrevState = make_ref(), % Will be discarded by loop_event_actions/9
NewActions =
if
is_list(Actions) ->
@@ -526,7 +545,7 @@ enter(Module, Opts, CallbackMode, State, Data, Server, Actions, Parent) ->
callback_mode => CallbackMode,
module => Module,
name => Name,
- state => OldState,
+ state => PrevState,
data => Data,
timer => undefined,
postponed => [],
@@ -534,7 +553,7 @@ enter(Module, Opts, CallbackMode, State, Data, Server, Actions, Parent) ->
loop_event_actions(
Parent, Debug, S, [],
{event,undefined}, % Will be discarded thanks to {postpone,false}
- OldState, State, Data, NewActions).
+ PrevState, State, Data, NewActions).
%%%==========================================================================
%%% gen callbacks
@@ -868,18 +887,18 @@ loop_event_result(
exit, Reason, ?STACKTRACE(), Debug, NewS, Q, Replies),
%% Since we got back here Replies was bad
terminate(Class, NewReason, Stacktrace, NewDebug, NewS, Q);
- {next_state,NewState,NewData}
- when CallbackMode =:= state_functions, is_atom(NewState);
+ {next_state,NextState,NewData}
+ when CallbackMode =:= state_functions, is_atom(NextState);
CallbackMode =/= state_functions ->
loop_event_actions(
Parent, Debug, S, Events, Event,
- State, NewState, NewData, []);
- {next_state,NewState,NewData,Actions}
- when CallbackMode =:= state_functions, is_atom(NewState);
+ State, NextState, NewData, []);
+ {next_state,NextState,NewData,Actions}
+ when CallbackMode =:= state_functions, is_atom(NextState);
CallbackMode =/= state_functions ->
loop_event_actions(
Parent, Debug, S, Events, Event,
- State, NewState, NewData, Actions);
+ State, NextState, NewData, Actions);
{keep_state,NewData} ->
loop_event_actions(
Parent, Debug, S, Events, Event,
@@ -902,13 +921,13 @@ loop_event_result(
end.
loop_event_actions(
- Parent, Debug, S, Events, Event, State, NewState, NewData, Actions) ->
+ Parent, Debug, S, Events, Event, State, NextState, NewData, Actions) ->
Postpone = false, % Shall we postpone this event, true or false
Hibernate = false,
Timeout = undefined,
NextEvents = [],
loop_event_actions(
- Parent, Debug, S, Events, Event, State, NewState, NewData,
+ Parent, Debug, S, Events, Event, State, NextState, NewData,
if
is_list(Actions) ->
Actions;
@@ -920,19 +939,19 @@ loop_event_actions(
%% Process all action()s
loop_event_actions(
Parent, Debug, S, Events, Event,
- State, NewState, NewData, [Action|Actions],
+ State, NextState, NewData, [Action|Actions],
Postpone, Hibernate, Timeout, NextEvents) ->
case Action of
%% Actions that set options
postpone ->
loop_event_actions(
Parent, Debug, S, Events, Event,
- State, NewState, NewData, Actions,
+ State, NextState, NewData, Actions,
true, Hibernate, Timeout, NextEvents);
{postpone,NewPostpone} when is_boolean(NewPostpone) ->
loop_event_actions(
Parent, Debug, S, Events, Event,
- State, NewState, NewData, Actions,
+ State, NextState, NewData, Actions,
NewPostpone, Hibernate, Timeout, NextEvents);
{postpone,_} ->
?TERMINATE(
@@ -940,12 +959,12 @@ loop_event_actions(
hibernate ->
loop_event_actions(
Parent, Debug, S, Events, Event,
- State, NewState, NewData, Actions,
+ State, NextState, NewData, Actions,
Postpone, true, Timeout, NextEvents);
{hibernate,NewHibernate} when is_boolean(NewHibernate) ->
loop_event_actions(
Parent, Debug, S, Events, Event,
- State, NewState, NewData, Actions,
+ State, NextState, NewData, Actions,
Postpone, NewHibernate, Timeout, NextEvents);
{hibernate,_} ->
?TERMINATE(
@@ -953,12 +972,12 @@ loop_event_actions(
{timeout,infinity,_} -> % Clear timer - it will never trigger
loop_event_actions(
Parent, Debug, S, Events, Event,
- State, NewState, NewData, Actions,
+ State, NextState, NewData, Actions,
Postpone, Hibernate, undefined, NextEvents);
{timeout,Time,_} = NewTimeout when is_integer(Time), Time >= 0 ->
loop_event_actions(
Parent, Debug, S, Events, Event,
- State, NewState, NewData, Actions,
+ State, NextState, NewData, Actions,
Postpone, Hibernate, NewTimeout, NextEvents);
{timeout,_,_} ->
?TERMINATE(
@@ -970,7 +989,7 @@ loop_event_actions(
NewDebug = do_reply(Debug, S, Caller, Reply),
loop_event_actions(
Parent, NewDebug, S, Events, Event,
- State, NewState, NewData, Actions,
+ State, NextState, NewData, Actions,
Postpone, Hibernate, Timeout, NextEvents);
false ->
?TERMINATE(
@@ -981,7 +1000,7 @@ loop_event_actions(
true ->
loop_event_actions(
Parent, Debug, S, Events, Event,
- State, NewState, NewData, Actions,
+ State, NextState, NewData, Actions,
Postpone, Hibernate, Timeout,
[{Type,Content}|NextEvents]);
false ->
@@ -996,7 +1015,7 @@ loop_event_actions(
%% End of actions list
loop_event_actions(
Parent, Debug, #{postponed := P0} = S, Events, Event,
- State, NewState, NewData, [],
+ State, NextState, NewData, [],
Postpone, Hibernate, Timeout, NextEvents) ->
%%
%% All options have been collected and next_events are buffered.
@@ -1011,7 +1030,7 @@ loop_event_actions(
end,
{Q2,P} = % Move all postponed events to queue if state change
if
- NewState =:= State ->
+ NextState =:= State ->
{Events,P1};
true ->
{lists:reverse(P1, Events),[]}
@@ -1024,9 +1043,9 @@ loop_event_actions(
Debug, S,
case Postpone of
true ->
- {postpone,Event,NewState};
+ {postpone,Event,NextState};
false ->
- {consume,Event,NewState}
+ {consume,Event,NextState}
end),
%% Have a peek on the event queue so we can avoid starting
%% the state timer unless we have to
@@ -1057,7 +1076,7 @@ loop_event_actions(
loop_events(
Parent, NewDebug,
S#{
- state := NewState,
+ state := NextState,
data := NewData,
timer := Timer,
postponed := P,