aboutsummaryrefslogtreecommitdiffstats
path: root/lib/stdlib
diff options
context:
space:
mode:
Diffstat (limited to 'lib/stdlib')
-rw-r--r--lib/stdlib/doc/src/digraph.xml2
-rw-r--r--lib/stdlib/doc/src/digraph_utils.xml7
-rw-r--r--lib/stdlib/doc/src/epp.xml1
-rw-r--r--lib/stdlib/doc/src/erl_anno.xml4
-rw-r--r--lib/stdlib/doc/src/erl_parse.xml12
-rw-r--r--lib/stdlib/doc/src/ets.xml12
-rw-r--r--lib/stdlib/doc/src/gen_statem.xml1779
-rw-r--r--lib/stdlib/doc/src/proc_lib.xml7
-rw-r--r--lib/stdlib/doc/src/sofs.xml3
-rw-r--r--lib/stdlib/src/beam_lib.erl2
-rw-r--r--lib/stdlib/src/epp.erl65
-rw-r--r--lib/stdlib/src/erl_compile.erl1
-rw-r--r--lib/stdlib/src/escript.erl1
-rw-r--r--lib/stdlib/src/gen_statem.erl493
-rw-r--r--lib/stdlib/src/otp_internal.erl2
-rw-r--r--lib/stdlib/src/proc_lib.erl19
-rw-r--r--lib/stdlib/src/stdlib.app.src2
-rw-r--r--lib/stdlib/src/supervisor.erl16
-rw-r--r--lib/stdlib/test/binary_module_SUITE.erl29
-rw-r--r--lib/stdlib/test/epp_SUITE.erl63
-rw-r--r--lib/stdlib/test/erl_lint_SUITE.erl6
-rw-r--r--lib/stdlib/test/ets_SUITE.erl32
-rw-r--r--lib/stdlib/test/gen_statem_SUITE.erl10
-rw-r--r--lib/stdlib/test/io_SUITE.erl44
-rw-r--r--lib/stdlib/test/io_proto_SUITE.erl3
-rw-r--r--lib/stdlib/test/rand_SUITE.erl28
-rw-r--r--lib/stdlib/test/select_SUITE.erl30
-rw-r--r--lib/stdlib/test/unicode_SUITE.erl24
28 files changed, 1343 insertions, 1354 deletions
diff --git a/lib/stdlib/doc/src/digraph.xml b/lib/stdlib/doc/src/digraph.xml
index 16dd789caf..1bb8eef247 100644
--- a/lib/stdlib/doc/src/digraph.xml
+++ b/lib/stdlib/doc/src/digraph.xml
@@ -104,14 +104,12 @@
</datatype>
<datatype>
<name>edge()</name>
- <desc><p><marker id="type-edge"/></p></desc>
</datatype>
<datatype>
<name name="label"/>
</datatype>
<datatype>
<name>vertex()</name>
- <desc><p><marker id="type-vertex"/></p></desc>
</datatype>
</datatypes>
<funcs>
diff --git a/lib/stdlib/doc/src/digraph_utils.xml b/lib/stdlib/doc/src/digraph_utils.xml
index 9bddee546f..e481711c50 100644
--- a/lib/stdlib/doc/src/digraph_utils.xml
+++ b/lib/stdlib/doc/src/digraph_utils.xml
@@ -120,13 +120,6 @@
considering all edges undirected.</p>
</description>
- <datatypes>
- <datatype>
- <name>digraph()</name>
- <desc><p><marker id="type-digraph"/>
- A digraph as returned by <c>digraph:new/0,1</c>.</p></desc>
- </datatype>
- </datatypes>
<funcs>
<func>
<name name="arborescence_root" arity="1"/>
diff --git a/lib/stdlib/doc/src/epp.xml b/lib/stdlib/doc/src/epp.xml
index 0802f0e47c..ac87f9c2b6 100644
--- a/lib/stdlib/doc/src/epp.xml
+++ b/lib/stdlib/doc/src/epp.xml
@@ -102,6 +102,7 @@
<func>
<name name="parse_erl_form" arity="1"/>
<fsummary>Return the next Erlang form from the opened Erlang source file</fsummary>
+ <type name="warning_info"/>
<desc>
<p>Returns the next Erlang form from the opened Erlang source file.
The tuple <c>{eof, <anno>Line</anno>}</c> is returned at end-of-file. The first
diff --git a/lib/stdlib/doc/src/erl_anno.xml b/lib/stdlib/doc/src/erl_anno.xml
index ddc8b8c765..9f775943c1 100644
--- a/lib/stdlib/doc/src/erl_anno.xml
+++ b/lib/stdlib/doc/src/erl_anno.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2015</year>
- <year>2015</year>
+ <year>2016</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -103,7 +103,7 @@
<datatypes>
<datatype>
<name>anno()</name>
- <desc><p><marker id="type-anno"/>A collection of annotations.</p>
+ <desc><p>A collection of annotations.</p>
</desc>
</datatype>
<datatype>
diff --git a/lib/stdlib/doc/src/erl_parse.xml b/lib/stdlib/doc/src/erl_parse.xml
index 13be488c33..32fce16d68 100644
--- a/lib/stdlib/doc/src/erl_parse.xml
+++ b/lib/stdlib/doc/src/erl_parse.xml
@@ -45,26 +45,22 @@
<datatypes>
<datatype>
<name>abstract_clause()</name>
- <desc><p><marker id="type-abstract_clause"/>
- Abstract form of an Erlang clause.</p>
+ <desc><p>Abstract form of an Erlang clause.</p>
</desc>
</datatype>
<datatype>
<name>abstract_expr()</name>
- <desc><p><marker id="type-abstract_expr"/>
- Abstract form of an Erlang expression.</p>
+ <desc><p>Abstract form of an Erlang expression.</p>
</desc>
</datatype>
<datatype>
<name>abstract_form()</name>
- <desc><p><marker id="type-abstract_form"/>
- Abstract form of an Erlang form.</p>
+ <desc><p>Abstract form of an Erlang form.</p>
</desc>
</datatype>
<datatype>
<name>abstract_type()</name>
- <desc><p><marker id="type-abstract_type"/>
- Abstract form of an Erlang type.</p>
+ <desc><p>Abstract form of an Erlang type.</p>
</desc>
</datatype>
<datatype>
diff --git a/lib/stdlib/doc/src/ets.xml b/lib/stdlib/doc/src/ets.xml
index 2d69c201bc..9fb7d227a3 100644
--- a/lib/stdlib/doc/src/ets.xml
+++ b/lib/stdlib/doc/src/ets.xml
@@ -98,10 +98,10 @@
All updates to single objects are guaranteed to be both <em>atomic</em>
and <em>isolated</em>. This means that an updating operation towards
a single object will either succeed or fail completely without any
- effect at all (atomicy).
+ effect at all (atomicity).
Nor can any intermediate results of the update be seen by other
processes (isolation). Some functions that update several objects
- state that they even guarantee atomicy and isolation for the entire
+ state that they even guarantee atomicity and isolation for the entire
operation. In database terms the isolation level can be seen as
"serializable", as if all isolated operations were carried out serially,
one after the other in a strict order.</p>
@@ -123,8 +123,9 @@
<p>Some of the functions uses a <em>match specification</em>,
match_spec. A brief explanation is given in
<seealso marker="#select/2">select/2</seealso>. For a detailed
- description, see the chapter "Match specifications in Erlang" in
- <em>ERTS User's Guide</em>.</p>
+ description, see chapter
+ <seealso marker="erts:match_spec">Match Specifications in Erlang</seealso>
+ in <em>ERTS User's Guide</em>.</p>
</section>
<datatypes>
@@ -134,8 +135,7 @@
<datatype>
<name>continuation()</name>
<desc>
- <p><marker id="type-continuation"/>
- Opaque continuation used by <seealso marker="#select/1">
+ <p>Opaque continuation used by <seealso marker="#select/1">
<c>select/1,3</c></seealso>, <seealso marker="#select_reverse/1">
<c>select_reverse/1,3</c></seealso>, <seealso
marker="#match/1">
diff --git a/lib/stdlib/doc/src/gen_statem.xml b/lib/stdlib/doc/src/gen_statem.xml
index ec7f267c64..0e7d6e53e9 100644
--- a/lib/stdlib/doc/src/gen_statem.xml
+++ b/lib/stdlib/doc/src/gen_statem.xml
@@ -29,39 +29,49 @@
<rev></rev>
</header>
<module>gen_statem</module>
- <modulesummary>Generic State Machine Behaviour</modulesummary>
+ <modulesummary>Generic state machine behavior.</modulesummary>
<description>
<p>
- A behaviour module for implementing a state machine. Two
+ This behavior module provides a state machine. Two
<seealso marker="#type-callback_mode"><em>callback modes</em></seealso>
- are supported. One for finite state machines
- (<seealso marker="gen_fsm"><c>gen_fsm</c></seealso> like)
- that requires the state to be an atom and uses that state as
- the name of the current callback function,
- and one without restriction on the state data type
- that uses one callback function for all states.
- </p>
- <p>
- This is a new behaviour in OTP-19.0.
- It has been thoroughly reviewed, is stable enough
- to be used by at least two heavy OTP applications, and is here to stay.
- But depending on user feedback, we do not expect
- but might find it necessary to make minor
- not backwards compatible changes into OTP-20.0,
- so its state can be designated as "not quite experimental"...
+ are supported:
</p>
+ <list type="bulleted">
+ <item>
+ <p>One for finite-state machines
+ (<seealso marker="gen_fsm"><c>gen_fsm</c></seealso> like),
+ which requires the state to be an atom and uses that state as
+ the name of the current callback function
+ </p>
+ </item>
+ <item>
+ <p>One without restriction on the state data type
+ that uses one callback function for all states
+ </p>
+ </item>
+ </list>
+ <note>
+ <p>
+ This is a new behavior in Erlang/OTP 19.0.
+ It has been thoroughly reviewed, is stable enough
+ to be used by at least two heavy OTP applications, and is here to stay.
+ Depending on user feedback, we do not expect
+ but can find it necessary to make minor
+ not backward compatible changes into Erlang/OTP 20.0.
+ </p>
+ </note>
<p>
- The <c>gen_statem</c> behaviour is intended to replace
+ The <c>gen_statem</c> behavior is intended to replace
<seealso marker="gen_fsm"><c>gen_fsm</c></seealso> for new code.
- It has the same features and add some really useful:
+ 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>A reply can be sent from a later state</item>
- <item>There can be multiple sys traceable replies</item>
+ <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>A reply can be sent from a later state.</item>
+ <item>There can be multiple <c>sys</c> traceable replies.</item>
</list>
<p>
The callback model(s) for <c>gen_statem</c> differs from
@@ -71,19 +81,16 @@
</p>
<p>
A generic state machine process (<c>gen_statem</c>) 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:statem">
- OTP Design Principles
- </seealso>
- for more information.
+ using this module has a standard set of interface functions
+ and includes functionality for tracing and error reporting.
+ It also fits into an OTP supervision tree. For more information, see
+ <seealso marker="doc/design_principles:statem">OTP Design Principles</seealso>.
</p>
<p>
A <c>gen_statem</c> 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>
+ callback module exporting a predefined set of functions.
+ The relationship between the behavior functions and the callback
+ functions is as follows:</p>
<pre>
gen_statem module Callback module
----------------- ---------------
@@ -103,59 +110,54 @@ erlang:'!' -----> Module:StateName/3
- -----> Module:code_change/4</pre>
<p>
Events are of different
- <seealso marker="#type-event_type">types</seealso>
+ <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 <c>gen_statem</c> 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.
+ the <c>gen_statem</c> terminates. However, an exception of class
+ <seealso marker="erts:erlang#throw/1"><c>throw</c></seealso>
+ is not regarded as an error but as a valid return.
</p>
- <marker id="state_function" />
+ <marker id="state_function"/>
<p>
The "<em>state function</em>" for a specific
<seealso marker="#type-state">state</seealso>
in a <c>gen_statem</c> is the callback function that is called
- for all events in this state, and is selected depending on which
+ 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 the server starts.
+ that the implementation specifies when the server starts.
</p>
<p>
When the
<seealso marker="#type-callback_mode"><em>callback mode</em></seealso>
- is <c>state_functions</c>, the state has to be an atom and
- is used as the state function name. See
- <seealso marker="#Module:StateName/3">
- <c>Module:StateName/3</c>
- </seealso>.
+ is <c>state_functions</c>, the state must be an atom and
+ is used as the state function name; see
+ <seealso marker="#Module:StateName/3"><c>Module:StateName/3</c></seealso>.
This gathers all code for a specific state
- in one function and hence dispatches on state first.
- Note that in this mode 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.
+ in one function as the <c>gen_statem</c> engine
+ branches depending on state name.
+ Notice that in this mode the mandatory callback function
+ <seealso marker="#Module:terminate/3"><c>Module:terminate/3</c></seealso>
+ makes the state name <c>terminate</c> unusable.
</p>
<p>
When the
<seealso marker="#type-callback_mode"><em>callback mode</em></seealso>
- is <c>handle_event_function</c> the state can be any term
+ is <c>handle_event_function</c>, the state can be any term
and the state function name is
- <seealso marker="#Module:handle_event/4">
- <c>Module:handle_event/4</c>
- </seealso>.
- This makes it easy to dispatch on state or on event as you desire.
+ <seealso marker="#Module:handle_event/4"><c>Module:handle_event/4</c></seealso>.
+ This makes it easy to branch depending on state or event as you desire.
Be careful about which events you handle in which
- states so you do not accidentally postpone one event
+ states so that you do not accidentally postpone an event
forever creating an infinite busy loop.
</p>
<p>
The <c>gen_statem</c> enqueues incoming events in order of arrival
and presents these to the
<seealso marker="#state_function">state function</seealso>
- in that order. The state function can postpone an event
+ in that order. The state function can postpone an event
so it is not retried in the current state.
After a state change the queue restarts with the postponed events.
</p>
@@ -163,91 +165,85 @@ erlang:'!' -----> Module:StateName/3
The <c>gen_statem</c> event queue model is sufficient
to emulate the normal process message queue with selective receive.
Postponing an event corresponds to not matching it
- in a receive statement and changing states corresponds
+ in a receive statement, and changing states corresponds
to entering a new receive statement.
</p>
<p>
The <seealso marker="#state_function">state function</seealso>
can insert events using the
- <seealso marker="#type-action">
- <c>action()</c> <c>next_event</c>
- </seealso>
+ <seealso marker="#type-action"><c>action()</c></seealso>
+ <c>next_event</c>
and such an event is inserted as the next to present
- to the state function. That is: as if it is
- the oldest incoming event. There is a dedicated
- <seealso marker="#type-event_type">
- <c>event_type()</c>
- </seealso>
- <c>internal</c> that can be used for such events making them impossible
+ to the state function. That is, as if it is
+ the oldest incoming event. A dedicated
+ <seealso marker="#type-event_type"><c>event_type()</c></seealso>
+ <c>internal</c> can be used for such events making them impossible
to mistake for external events.
</p>
<p>
Inserting an event replaces the trick of calling your own
state handling functions that you often would have to
- resort to in for example <seealso marker="gen_fsm"><c>gen_fsm</c></seealso>
+ resort to in, for example,
+ <seealso marker="gen_fsm"><c>gen_fsm</c></seealso>
to force processing an inserted event before others.
- A warning, though: if you in <c>gen_statem</c> for example
- postpone an event in one state and then call some other state function of yours,
- you have not changed states and hence the postponed event will not be retried,
- which is logical but might be confusing.
</p>
+ <note>
+ <p>If you in <c>gen_statem</c>, for example, postpone
+ an event in one state and then call another state function
+ of yours, you have not changed states and hence the postponed event
+ is not retried, which is logical but can be confusing.
+ </p>
+ </note>
<p>
- See the type
- <seealso marker="#type-transition_option">
- <c>transition_option()</c>
- </seealso>
- for the details of a state transition.
+ For the details of a state transition, see type
+ <seealso marker="#type-transition_option"><c>transition_option()</c></seealso>.
</p>
<p>
- A <c>gen_statem</c> handles system messages as documented in
+ A <c>gen_statem</c> handles system messages as described in
<seealso marker="sys"><c>sys</c></seealso>.
- The <c>sys</c>module can be used for debugging a <c>gen_statem</c>.
+ The <c>sys</c> module can be used for debugging a <c>gen_statem</c>.
</p>
<p>
- Note that a <c>gen_statem</c> does not trap exit signals
+ Notice that a <c>gen_statem</c> does not trap exit signals
automatically, this must be explicitly initiated in
the callback module (by calling
- <seealso marker="erts:erlang#process_flag/2">
- <c>process_flag(trap_exit, true)</c></seealso>.
+ <seealso marker="erts:erlang#process_flag/2"><c>process_flag(trap_exit, true)</c></seealso>.
</p>
<p>
Unless otherwise stated, all functions in this module fail if
the specified <c>gen_statem</c> does not exist or
- if bad arguments are given.
+ if bad arguments are specified.
</p>
<p>
The <c>gen_statem</c> process can go into hibernation; see
- <seealso marker="proc_lib#hibernate/3">
- <c>proc_lib:hibernate/3</c>.
- </seealso>
+ <seealso marker="proc_lib#hibernate/3"><c>proc_lib:hibernate/3</c></seealso>.
It is done when a
<seealso marker="#state_function">state function</seealso> or
<seealso marker="#Module:init/1"><c>Module:init/1</c></seealso>
specifies <c>hibernate</c> in the returned
<seealso marker="#type-action"><c>Actions</c></seealso>
- list. This feature might be useful to reclaim process heap memory
+ list. This feature can be useful to reclaim process heap memory
while the server is expected to be idle for a long time.
- However, use this feature with care
- since hibernation can be too costly
+ However, use this feature with care,
+ as hibernation can be too costly
to use after every event; see
- <seealso marker="erts:erlang#hibernate/3">
- <c>erlang:hibernate/3</c>.
- </seealso>
+ <seealso marker="erts:erlang#hibernate/3"><c>erlang:hibernate/3</c></seealso>.
</p>
</description>
<section>
- <title>EXAMPLE</title>
+ <title>Example</title>
<p>
- This example shows a simple pushbutton model
+ The following example shows a simple pushbutton model
for a toggling pushbutton implemented with
<seealso marker="#type-callback_mode"><em>callback mode</em></seealso>
<c>state_functions</c>.
You can push the button and it replies if it went on or off,
and you can ask for a count of how many times it has been
- pushed to on.
+ pushed to switch on.
</p>
- <p>This is the complete callback module file <c>pushbutton.erl</c>:</p>
+ <p>The following is the complete callback module file
+ <c>pushbutton.erl</c>:</p>
<code type="erl">
-module(pushbutton).
-behaviour(gen_statem).
@@ -305,7 +301,7 @@ handle_event(_, _, Data) ->
%% Ignore all other events
{keep_state,Data}.
</code>
- <p>And this is a shell session when running it:</p>
+ <p>The following is a shell session when running it:</p>
<pre>
1> pushbutton:start().
{ok,&lt;0.36.0>}
@@ -326,12 +322,11 @@ ok
in function gen:do_for_proc/2 (gen.erl, line 261)
in call from gen_statem:call/3 (gen_statem.erl, line 386)
</pre>
-
<p>
- And just to compare styles here is the same example using
+ 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 here is code to replace
- from the <c>init/1</c> function of the <c>pushbutton.erl</c>
+ <c>state_functions</c>, or rather the code to replace
+ from function <c>init/1</c> of the <c>pushbutton.erl</c>
example file above:
</p>
<code type="erl">
@@ -364,107 +359,108 @@ handle_event(_, _, State, Data) ->
<datatypes>
<datatype>
- <name name="server_name" />
+ <name name="server_name"/>
<desc>
<p>
Name specification to use when starting
- a <c>gen_statem</c> server. See
- <seealso marker="#start_link/3">
- <c>start_link/3</c>
- </seealso>
+ a <c>gen_statem</c> 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.
+ <seealso marker="#type-server_ref"><c>server_ref()</c></seealso>
+ below.
</p>
</desc>
</datatype>
<datatype>
- <name name="server_ref" />
+ <name name="server_ref"/>
<desc>
<p>
Server specification to use when addressing
a <c>gen_statem</c> server.
See <seealso marker="#call/2"><c>call/2</c></seealso> and
- <seealso marker="#type-server_name">
- <c>server_name()</c>
- </seealso>
+ <seealso marker="#type-server_name"><c>server_name()</c></seealso>
above.
</p>
<p>It can be:</p>
<taglist>
- <tag><c>pid()</c><br />
- <c>LocalName</c></tag>
- <item>The <c>gen_statem</c> is locally registered.</item>
- <tag><c>Name, Node</c></tag>
+ <tag><c>pid() | LocalName</c></tag>
<item>
- The <c>gen_statem</c> is locally registered
- on another node.
+ <p>
+ The <c>gen_statem</c> is locally registered.
+ </p>
+ </item>
+ <tag><c>{Name,Node}</c></tag>
+ <item>
+ <p>
+ The <c>gen_statem</c> is locally registered
+ on another node.
+ </p>
</item>
- <tag><c>GlobalName</c></tag>
+ <tag><c>{global,GlobalName}</c></tag>
<item>
- The <c>gen_statem</c> is globally registered
- in <seealso marker="kernel:global"><c>global</c></seealso>.
+ <p>
+ The <c>gen_statem</c> is globally registered in
+ <seealso marker="kernel:global"><c>kernel:global</c></seealso>.
+ </p>
</item>
- <tag><c>RegMod, ViaName</c></tag>
+ <tag><c>{via,RegMod,ViaName}</c></tag>
<item>
- The <c>gen_statem</c> 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>.
+ <p>
+ The <c>gen_statem</c> is registered in
+ an alternative process registry.
+ The registry callback module <c>RegMod</c>
+ is to export functions
+ <c>register_name/2</c>, <c>unregister_name/1</c>,
+ <c>whereis_name/1</c>, and <c>send/2</c>,
+ which are to behave like the corresponding functions in
+ <seealso marker="kernel:global"><c>kernel:global</c></seealso>.
+ Thus, <c>{via,global,GlobalName}</c> is the same as
+ <c>{global,GlobalName}</c>.
+ </p>
</item>
</taglist>
</desc>
</datatype>
<datatype>
- <name name="debug_opt" />
+ <name name="debug_opt"/>
<desc>
<p>
Debug option that can be used when starting
- a <c>gen_statem</c> server through for example
+ a <c>gen_statem</c> server through, for example,
<seealso marker="#enter_loop/5"><c>enter_loop/5</c></seealso>.
</p>
<p>
- For every entry in <c><anno>Dbgs</anno></c>
+ For every entry in <c><anno>Dbgs</anno></c>,
the corresponding function in
- <seealso marker="sys"><c>sys</c></seealso> will be called.
+ <seealso marker="sys"><c>sys</c></seealso> is called.
</p>
</desc>
</datatype>
<datatype>
- <name name="start_opt" />
+ <name name="start_opt"/>
<desc>
<p>
Options that can be used when starting
- a <c>gen_statem</c> server through for example
+ a <c>gen_statem</c> server through, for example,
<seealso marker="#start_link/3"><c>start_link/3</c></seealso>.
</p>
</desc>
</datatype>
<datatype>
- <name name="start_ret" />
+ <name name="start_ret"/>
<desc>
<p>
- Return value from the start functions for_example
+ Return value from the start functions, for example,
<seealso marker="#start_link/3"><c>start_link/3</c></seealso>.
</p>
</desc>
</datatype>
-
<datatype>
- <name name="from" />
+ <name name="from"/>
<desc>
<p>
- Destination to use when replying through for example the
- <seealso marker="#type-action">
- <c>action()</c>
- </seealso>
+ Destination to use when replying through, for example, the
+ <seealso marker="#type-action"><c>action()</c></seealso>
<c>{reply,From,Reply}</c>
to a process that has called the <c>gen_statem</c> server using
<seealso marker="#call/2"><c>call/2</c></seealso>.
@@ -472,231 +468,228 @@ handle_event(_, _, State, Data) ->
</desc>
</datatype>
<datatype>
- <name name="state" />
+ <name name="state"/>
<desc>
<p>
- After a state change (<c>NextState =/= State</c>)
+ After a state change (<c>NextState =/= State</c>),
all postponed events are retried.
</p>
</desc>
</datatype>
<datatype>
- <name name="state_name" />
+ <name name="state_name"/>
<desc>
<p>
If the
<seealso marker="#type-callback_mode"><em>callback mode</em></seealso>
is <c>state_functions</c>,
- the state has to be of this type.
+ the state must be of this type.
</p>
</desc>
</datatype>
<datatype>
- <name name="data" />
+ <name name="data"/>
<desc>
<p>
A term in which the state machine implementation
- should store any server data it needs. The difference between
+ is to store any server data it needs. The difference between
this and the <seealso marker="#type-state"><c>state()</c></seealso>
itself is that a change in this data does not cause
- postponed events to be retried. Hence if a change
+ postponed events to be retried. Hence, if a change
in this data would change the set of events that
- are handled than that data item should be made
+ are handled, then that data item is to be made
a part of the state.
</p>
</desc>
</datatype>
<datatype>
- <name name="event_type" />
+ <name name="event_type"/>
<desc>
<p>
- External events are of 3 different type:
- <c>{call,<anno>From</anno>}</c>, <c>cast</c> or <c>info</c>.
+ External events are of three types:
+ <c>{call,<anno>From</anno>}</c>, <c>cast</c>, or <c>info</c>.
<seealso marker="#call/2">Calls</seealso>
(synchronous) and
<seealso marker="#cast/2">casts</seealso>
originate from the corresponding API functions.
- For calls the event contain whom to reply to.
+ 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>. It is also possible for the state machine
- implementation to generate events of types
+ to the <c>gen_statem</c>. Also, the state machine
+ implementation can generate events of types
<c>timeout</c> and <c>internal</c> to itself.
</p>
</desc>
</datatype>
<datatype>
- <name name="callback_mode" />
+ <name name="callback_mode"/>
<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-7</c></seealso>,
+ <seealso marker="#enter_loop/5"><c>enter_loop/5,6,7</c></seealso>,
and with the return value from
- <seealso marker="#Module:code_change/4">
- <c>Module:code_change/4</c>.
- </seealso>
+ <seealso marker="#Module:code_change/4"><c>Module:code_change/4</c></seealso>.
</p>
<taglist>
<tag><c>state_functions</c></tag>
<item>
- The state has to be of type
- <seealso marker="#type-state_name"><c>state_name()</c></seealso>
- and one callback function per state that is
- <seealso marker="#Module:StateName/3">
- <c>Module:StateName/3</c>
- </seealso>
- is used.
+ <p>
+ The state must be of type
+ <seealso marker="#type-state_name"><c>state_name()</c></seealso>
+ and one callback function per state, that is,
+ <seealso marker="#Module:StateName/3"><c>Module:StateName/3</c></seealso>,
+ is used.
+ </p>
</item>
<tag><c>handle_event_function</c></tag>
<item>
- The state can be any term and the callback function
- <seealso marker="#Module:handle_event/4">
- <c>Module:handle_event/4</c>
- </seealso>
- is used for all states.
+ <p>
+ The state can be any term and the callback function
+ <seealso marker="#Module:handle_event/4"><c>Module:handle_event/4</c></seealso>
+ is used for all states.
+ </p>
</item>
</taglist>
</desc>
</datatype>
<datatype>
- <name name="transition_option" />
+ <name name="transition_option"/>
<desc>
<p>
- Transition options may be set by
+ Transition options can be set by
<seealso marker="#type-action">actions</seealso>
- and they modify some details below in how
+ and they modify the following in how
the state transition is done:
</p>
<list type="ordered">
<item>
- All
- <seealso marker="#type-action">actions</seealso>
- are processed in order of appearance.
+ <p>
+ All
+ <seealso marker="#type-action">actions</seealso>
+ are processed in order of appearance.
+ </p>
</item>
<item>
- If
- <seealso marker="#type-postpone">
- <c>postpone()</c>
- </seealso>
- is <c>true</c>
- the current event is postponed.
+ <p>
+ If
+ <seealso marker="#type-postpone"><c>postpone()</c></seealso>
+ is <c>true</c>,
+ the current event is postponed.
+ </p>
</item>
<item>
- If the state changes the queue of incoming events
- is reset to start with the oldest postponed.
+ <p>
+ If the state changes, the queue of incoming events
+ is reset to start with the oldest postponed.
+ </p>
</item>
<item>
- All events stored with
- <seealso marker="#type-action">
- <c>action()</c>
- </seealso>
- <c>next_event</c>
- are inserted in the queue to be processed before
- all other events.
+ <p>
+ All events stored with
+ <seealso marker="#type-action"><c>action()</c></seealso>
+ <c>next_event</c>
+ are inserted in the queue to be processed before
+ all other events.
+ </p>
</item>
<item>
- If an
- <seealso marker="#type-event_timeout">
- <c>event_timeout()</c>
- </seealso>
- is set through
- <seealso marker="#type-action">
- <c>action()</c>
- </seealso>
- <c>timeout</c>
- an event timer may be started or a timeout zero event
- may be enqueued.
+ <p>
+ If an
+ <seealso marker="#type-event_timeout"><c>event_timeout()</c></seealso>
+ is set through
+ <seealso marker="#type-action"><c>action()</c></seealso>
+ <c>timeout</c>,
+ an event timer can be started or a time-out zero event
+ can be enqueued.
+ </p>
</item>
<item>
- The (possibly new)
- <seealso marker="#state_function">state function</seealso>
- is called with the oldest enqueued event if there is any,
- otherwise the <c>gen_statem</c> goes into <c>receive</c>
- or hibernation
- (if
- <seealso marker="#type-hibernate">
- <c>hibernate()</c>
- </seealso>
- is <c>true</c>)
- to wait for the next message. In hibernation the next
- non-system event awakens the <c>gen_statem</c>, or rather
- the next incoming message awakens the <c>gen_statem</c>
- but if it is a system event
- it goes right back into hibernation.
+ <p>
+ The (possibly new)
+ <seealso marker="#state_function">state function</seealso>
+ is called with the oldest enqueued event if there is any,
+ otherwise the <c>gen_statem</c> goes into <c>receive</c>
+ or hibernation
+ (if
+ <seealso marker="#type-hibernate"><c>hibernate()</c></seealso>
+ is <c>true</c>)
+ to wait for the next message. In hibernation the next
+ non-system event awakens the <c>gen_statem</c>, or rather
+ the next incoming message awakens the <c>gen_statem</c>,
+ but if it is a system event
+ it goes right back into hibernation.
+ </p>
</item>
</list>
</desc>
</datatype>
<datatype>
- <name name="postpone" />
+ <name name="postpone"/>
<desc>
<p>
- If <c>true</c> postpone the current event and retry
+ If <c>true</c>, postpones the current event and retries
it when the state changes
(<c>NextState =/= State</c>).
</p>
</desc>
</datatype>
<datatype>
- <name name="hibernate" />
+ <name name="hibernate"/>
<desc>
<p>
- If <c>true</c> hibernate the <c>gen_statem</c>
+ If <c>true</c>, hibernates the <c>gen_statem</c>
by calling
- <seealso marker="proc_lib#hibernate/3">
- <c>proc_lib:hibernate/3</c>
- </seealso>
+ <seealso marker="proc_lib#hibernate/3"><c>proc_lib:hibernate/3</c></seealso>
before going into <c>receive</c>
to wait for a new external event.
If there are enqueued events,
- to prevent receiving any new event; a
- <seealso marker="erts:erlang#garbage_collect/0">
- <c>garbage_collect/0</c>
- </seealso> is done instead to simulate
+ to prevent receiving any new event, an
+ <seealso marker="erts:erlang#garbage_collect/0"><c>erlang:garbage_collect/0</c></seealso>
+ is done instead to simulate
that the <c>gen_statem</c> entered hibernation
and immediately got awakened by the oldest enqueued event.
</p>
</desc>
</datatype>
<datatype>
- <name name="event_timeout" />
+ <name name="event_timeout"/>
<desc>
<p>
- Generate an event of
+ Generates an event of
<seealso marker="#type-event_type"><c>event_type()</c></seealso>
<c>timeout</c>
- after this time (in milliseconds) unless some other
- event arrives in which case this timeout is cancelled.
- Note that a retried or inserted event
- counts just like a new in this respect.
+ after this time (in milliseconds) unless another
+ event arrives in which case this time-out is cancelled.
+ Notice that a retried or inserted event
+ counts like a new in this respect.
</p>
<p>
- If the value is <c>infinity</c> no timer is started since
- it will never trigger anyway.
+ If the value is <c>infinity</c>, no timer is started, as
+ it never triggers anyway.
</p>
<p>
- If the value is <c>0</c> the timeout event is immediately enqueued
- unless there already are enqueued events since then the
- timeout is immediately cancelled.
- This is a feature ensuring that a timeout <c>0</c> event
- will be processed before any not yet received external event.
+ If the value is <c>0</c>, the time-out event is immediately enqueued
+ unless there already are enqueued events, as the
+ time-out is then immediately cancelled.
+ This is a feature ensuring that a time-out <c>0</c> event
+ is processed before any not yet received external event.
</p>
<p>
- Note that it is not possible nor needed to cancel this timeout
- since it is cancelled automatically by any other event.
+ Notice that it is not possible or needed to cancel this time-out,
+ as it is cancelled automatically by any other event.
</p>
</desc>
</datatype>
<datatype>
- <name name="action" />
+ <name name="action"/>
<desc>
<p>
- These state transition actions may be invoked by
+ These state transition actions can be invoked by
returning them from the
- <seealso marker="#state_function">state function</seealso>,
- from <seealso marker="#Module:init/1"><c>Module:init/1</c></seealso>
+ <seealso marker="#state_function">state function</seealso>, from
+ <seealso marker="#Module:init/1"><c>Module:init/1</c></seealso>
or by giving them to
<seealso marker="#enter_loop/6"><c>enter_loop/6,7</c></seealso>.
</p>
@@ -705,91 +698,81 @@ handle_event(_, _, State, Data) ->
</p>
<p>
Actions that set
- <seealso marker="#type-transition_option">
- transition options
- </seealso>
- overrides any previous of the same type,
+ <seealso marker="#type-transition_option">transition options</seealso>
+ override any previous of the same type,
so the last in the containing list wins.
- For example the last
- <seealso marker="#type-event_timeout">
- <c>event_timeout()</c>
- </seealso>
+ For example, the last
+ <seealso marker="#type-event_timeout"><c>event_timeout()</c></seealso>
overrides any other <c>event_timeout()</c> in the list.
</p>
<taglist>
<tag><c>postpone</c></tag>
<item>
- Set the
- <seealso marker="#type-transition_option">
- <c>transition_option()</c>
- </seealso>
- <seealso marker="#type-postpone">
- <c>postpone()</c>
- </seealso>
- for this state transition.
- This action is ignored when returned from
- <seealso marker="#Module:init/1"><c>Module:init/1</c></seealso>
- or given to
- <seealso marker="#enter_loop/5"><c>enter_loop/5,6</c></seealso>
- since there is no event to postpone in those cases.
+ <p>
+ Sets the
+ <seealso marker="#type-transition_option"><c>transition_option()</c></seealso>
+ <seealso marker="#type-postpone"><c>postpone()</c></seealso>
+ for this state transition.
+ This action is ignored when returned from
+ <seealso marker="#Module:init/1"><c>Module:init/1</c></seealso>
+ or given to
+ <seealso marker="#enter_loop/5"><c>enter_loop/5,6</c></seealso>,
+ as there is no event to postpone in those cases.
+ </p>
</item>
<tag><c>hibernate</c></tag>
<item>
- Set the
- <seealso marker="#type-transition_option">
- <c>transition_option()</c>
- </seealso>
- <seealso marker="#type-hibernate">
- <c>hibernate()</c>
- </seealso>
- for this state transition.
+ <p>
+ Sets the
+ <seealso marker="#type-transition_option"><c>transition_option()</c></seealso>
+ <seealso marker="#type-hibernate"><c>hibernate()</c></seealso>
+ for this state transition.
+ </p>
</item>
<tag><c>Timeout</c></tag>
<item>
- Short for <c>{timeout,Timeout,Timeout}</c> that is
- the timeout message is the timeout time.
- This form exists to make the
- <seealso marker="#state_function">state function</seealso>
- return value <c>{next_state,NextState,NewData,Timeout}</c>
- allowed like for
- <seealso marker="gen_fsm#Module:StateName/2">
- <c>gen_fsm Module:StateName/2</c>.
- </seealso>
+ <p>
+ Short for <c>{timeout,Timeout,Timeout}</c>, that is,
+ the time-out message is the time-out time.
+ This form exists to make the
+ <seealso marker="#state_function">state function</seealso>
+ return value <c>{next_state,NextState,NewData,Timeout}</c>
+ allowed like for <c>gen_fsm</c>'s
+ <seealso marker="gen_fsm#Module:StateName/2"><c>Module:StateName/2</c></seealso>.
+ </p>
</item>
<tag><c>timeout</c></tag>
<item>
- Set 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>.
+ <p>
+ 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>.
+ </p>
</item>
<tag><c>reply_action()</c></tag>
- <item>Reply to a caller.</item>
+ <item>
+ <p>
+ Replies to a caller.
+ </p>
+ </item>
<tag><c>next_event</c></tag>
<item>
- Store the given <c><anno>EventType</anno></c>
+ <p>
+ Stores the specified <c><anno>EventType</anno></c>
and <c><anno>EventContent</anno></c> for insertion after all
actions have been executed.
- </item>
- <item>
+ </p>
<p>
The stored events are inserted in the queue as the next to process
- before any already queued events. The order of these stored events
- is preserved so the first <c>next_event</c> in the containing list
- will become the first to process.
+ before any already queued events. The order of these stored events
+ is preserved, so the first <c>next_event</c> in the containing
+ list becomes the first to process.
</p>
- </item>
- <item>
<p>
An event of type
- <seealso marker="#type-event_type">
- <c>internal</c>
- </seealso>
- should be used when you want to reliably distinguish
+ <seealso marker="#type-event_type"><c>internal</c></seealso>
+ is to be used when you want to reliably distinguish
an event inserted this way from any external event.
</p>
</item>
@@ -797,303 +780,126 @@ handle_event(_, _, State, Data) ->
</desc>
</datatype>
<datatype>
- <name name="reply_action" />
+ <name name="reply_action"/>
<desc>
<p>
- Reply to a caller waiting for a reply in
+ Replies to a caller waiting for a reply in
<seealso marker="#call/2"><c>call/2</c></seealso>.
- <c><anno>From</anno></c> must be the term from the
- <seealso marker="#type-event_type">
- <c>{call,<anno>From</anno>}</c>
- </seealso>
- argument to the
+ <c><anno>From</anno></c> must be the term from argument
+ <seealso marker="#type-event_type"><c>{call,<anno>From</anno>}</c></seealso>
+ to the
<seealso marker="#state_function">state function</seealso>.
</p>
</desc>
</datatype>
<datatype>
- <name name="state_function_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>
+ <p>
+ The <c>gen_statem</c> does a state transition to
+ <c><anno>NextStateName</anno></c>
+ (which can be the same as the current state),
+ sets <c><anno>NewData</anno></c>,
+ and executes all <c><anno>Actions</anno></c>.
+ </p>
</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.
+ will hold in any future version of <c>gen_statem</c>.
</p>
</desc>
</datatype>
<datatype>
- <name name="handle_event_result" />
+ <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>
+ <p>
+ The <c>gen_statem</c> does a state transition to
+ <c><anno>NextState</anno></c>
+ (which can be the same as the current state),
+ sets <c><anno>NewData</anno></c>,
+ and executes all <c><anno>Actions</anno></c>.
+ </p>
</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.
+ will hold in any future version of <c>gen_statem</c>.
</p>
</desc>
</datatype>
<datatype>
- <name name="common_state_callback_result" />
+ <name name="common_state_callback_result"/>
<desc>
<taglist>
<tag><c>stop</c></tag>
<item>
- Terminate the <c>gen_statem</c> by calling
- <seealso marker="#Module:terminate/3">
- <c>Module:terminate/3</c>
- </seealso>
- with <c>Reason</c> and
- <c><anno>NewData</anno></c>, if given.
+ <p>
+ Terminates the <c>gen_statem</c> by calling
+ <seealso marker="#Module:terminate/3"><c>Module:terminate/3</c></seealso>
+ with <c>Reason</c> and
+ <c><anno>NewData</anno></c>, if specified.
+ </p>
</item>
<tag><c>stop_and_reply</c></tag>
<item>
- Send all <c><anno>Replies</anno></c>
- then terminate the <c>gen_statem</c> by calling
- <seealso marker="#Module:terminate/3">
- <c>Module:terminate/3</c>
- </seealso>
- with <c>Reason</c> and
- <c><anno>NewData</anno></c>, if given.
+ <p>
+ Sends all <c><anno>Replies</anno></c>,
+ then terminates the <c>gen_statem</c> by calling
+ <seealso marker="#Module:terminate/3"><c>Module:terminate/3</c></seealso>
+ with <c>Reason</c> and
+ <c><anno>NewData</anno></c>, if specified.
+ </p>
</item>
<tag><c>keep_state</c></tag>
<item>
- The <c>gen_statem</c> will keep the current state, or
- do a state transition to the current state if you like,
- set <c><anno>NewData</anno></c>
- and execute all <c><anno>Actions</anno></c>.
- This is the same as
- <c>{next_state,CurrentState,<anno>NewData</anno>,<anno>Actions</anno>}</c>.
+ <p>
+ The <c>gen_statem</c> keeps the current state, or
+ does a state transition to the current state if you like,
+ sets <c><anno>NewData</anno></c>,
+ and executes all <c><anno>Actions</anno></c>.
+ This is the same as
+ <c>{next_state,CurrentState,<anno>NewData</anno>,<anno>Actions</anno>}</c>.
+ </p>
</item>
<tag><c>keep_state_and_data</c></tag>
<item>
- The <c>gen_statem</c> will keep the current state or
- do a state transition to the current state if you like,
- keep the current server data,
- and execute all <c><anno>Actions</anno></c>.
- This is the same as
- <c>{next_state,CurrentState,CurrentData,<anno>Actions</anno>}</c>.
+ <p>
+ The <c>gen_statem</c> keeps the current state or
+ does a state transition to the current state if you like,
+ keeps the current server data,
+ and executes all <c><anno>Actions</anno></c>.
+ This is the same as
+ <c>{next_state,CurrentState,CurrentData,<anno>Actions</anno>}</c>.
+ </p>
</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.
+ will hold in any future version of <c>gen_statem</c>.
</p>
</desc>
</datatype>
</datatypes>
<funcs>
-
- <func>
- <name name="start_link" arity="3" />
- <name name="start_link" arity="4" />
- <fsummary>Create a linked <c>gen_statem</c> process</fsummary>
- <desc>
- <p>
- Creates a <c>gen_statem</c> 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 <c>gen_statem</c> shall be part of
- a supervision tree so it gets linked to its supervisor.
- </p>
- <p>
- The <c>gen_statem</c> 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 <c>gen_statem</c>.
- If the <c>gen_statem</c> is started with <c>start_link/3</c>
- no <c><anno>ServerName</anno></c> is provided and
- the <c>gen_statem</c> 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>Opts</anno></c>, the <c>gen_statem</c>
- 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>Opts</anno></c>, debugging through
- <seealso marker="sys"><c>sys</c></seealso> is activated.
- </p>
- <p>
- If the option <c>{spawn_opt,SpawnOpts}</c> is present in
- <c><anno>Opts</anno></c>, <c>SpawnOpts</c> will be passed
- as option list to
- <seealso marker="erts:erlang#spawn_opt/2"><c>spawn_opt/2</c></seealso>
- which is used to spawn the <c>gen_statem</c> process.
- </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 <c>gen_statem</c> 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 <c>gen_statem</c>.
- 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 <c>gen_statem</c> process</fsummary>
- <desc>
- <p>
- Creates a stand-alone <c>gen_statem</c> 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"><c>start_link/3,4</c></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 <c>gen_statem</c>
- <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 <c>gen_statem</c> will call
- <seealso marker="#Module:terminate/3">
- <c>Module:terminate/3</c>
- </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">
- <c>error_logger:format/2</c>.
- </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 <c>gen_statem</c></fsummary>
+ <name name="call" arity="2"/>
+ <name name="call" arity="3"/>
+ <fsummary>Make a synchronous call to a <c>gen_statem</c>.</fsummary>
<desc>
<p>
Makes a synchronous call to the <c>gen_statem</c>
- <seealso marker="#type-server_ref">
- <c><anno>ServerRef</anno></c>
- </seealso>
+ <seealso marker="#type-server_ref"><c><anno>ServerRef</anno></c></seealso>
by sending a request
and waiting until its reply arrives.
- The <c>gen_statem</c> will call the
+ The <c>gen_statem</c> calls the
<seealso marker="#state_function">state function</seealso> with
<seealso marker="#type-event_type"><c>event_type()</c></seealso>
<c>{call,From}</c> and event content
@@ -1108,43 +914,41 @@ handle_event(_, _, State, Data) ->
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
+ <p>
+ <c><anno>Timeout</anno></c> is an integer &gt; 0,
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
+ which is the default. If no reply is received within
the specified time, the function call fails.
</p>
<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
+ 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>
- The call may fail for example if the <c>gen_statem</c> dies
+ <p>
+ The call can fail, for example, if the <c>gen_statem</c> dies
before or during this function call.
</p>
</desc>
</func>
<func>
- <name name="cast" arity="2" />
- <fsummary>Send an asynchronous event to a <c>gen_statem</c></fsummary>
+ <name name="cast" arity="2"/>
+ <fsummary>Send an asynchronous event to a <c>gen_statem</c>.</fsummary>
<desc>
<p>
Sends an asynchronous event to the <c>gen_statem</c>
- <seealso marker="#type-server_ref">
- <c><anno>ServerRef</anno></c>
- </seealso>
+ <seealso marker="#type-server_ref"><c><anno>ServerRef</anno></c></seealso>
and returns <c>ok</c> immediately,
ignoring if the destination node or <c>gen_statem</c>
does not exist.
- The <c>gen_statem</c> will call the
+ The <c>gen_statem</c> calls 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
@@ -1154,68 +958,29 @@ handle_event(_, _, State, Data) ->
</func>
<func>
- <name name="reply" arity="1" />
- <name name="reply" arity="2" />
- <fsummary>Reply to a caller</fsummary>
- <desc>
- <p>
- This function can be used by a <c>gen_statem</c>
- to explicitly send a reply to a process that waits in
- <seealso marker="#call/2"><c>call/2</c></seealso>
- when the reply cannot be defined in
- the return value of a
- <seealso marker="#state_function">state function</seealso>.
- </p>
- <p>
- <c><anno>From</anno></c> must be the term from the
- <seealso marker="#type-event_type">
- <c>{call,<anno>From</anno>}</c>
- </seealso>
- argument to the
- <seealso marker="#state_function">state function</seealso>.
- <c><anno>From</anno></c> and <c><anno>Reply</anno></c>
- can also be specified using a
- <seealso marker="#type-reply_action">
- <c>reply_action()</c>
- </seealso>
- and multiple replies with a list of them.
- </p>
- <note>
- <p>
- A reply sent with this function will not be visible
- in <seealso marker="sys"><c>sys</c></seealso> debug output.
- </p>
- </note>
- </desc>
- </func>
-
- <func>
- <name name="enter_loop" arity="5" />
- <fsummary>Enter the <c>gen_statem</c> receive loop</fsummary>
+ <name name="enter_loop" arity="5"/>
+ <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="#type-server_name">
- <c>server_name()</c>
- </seealso>
+ <seealso marker="#type-server_name"><c>server_name()</c></seealso>
must have been registered.
</p>
</desc>
</func>
+
<func>
- <name name="enter_loop" arity="6" />
- <fsummary>Enter the <c>gen_statem</c> receive loop</fsummary>
+ <name name="enter_loop" arity="6"/>
+ <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>
+ 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>
except that no
- <seealso marker="#type-server_name">
- <c>server_name()</c>
- </seealso>
+ <seealso marker="#type-server_name"><c>server_name()</c></seealso>
must have been registered and
<c>Actions = <anno>Server_or_Actions</anno></c>.
</p>
@@ -1228,73 +993,350 @@ handle_event(_, _, State, Data) ->
</p>
</desc>
</func>
+
<func>
- <name name="enter_loop" arity="7" />
- <fsummary>Enter the <c>gen_statem</c> receive loop</fsummary>
+ <name name="enter_loop" arity="7"/>
+ <fsummary>Enter the <c>gen_statem</c> receive loop.</fsummary>
<desc>
- <p>
- Makes an the calling process become a <c>gen_statem</c>.
- Does not return, instead the calling process will enter
- the <c>gen_statem</c> receive loop and become
+ <p>
+ Makes the calling process become a <c>gen_statem</c>.
+ Does not return, instead the calling process enters
+ the <c>gen_statem</c> receive loop and becomes
a <c>gen_statem</c> 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>.
+ <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>
+ <p>
This function is useful when a more complex initialization
- procedure is needed than
- the <c>gen_statem</c> behaviour provides.
+ procedure is needed than
+ the <c>gen_statem</c> behavior provides.
</p>
- <p>
- <c><anno>Module</anno></c>, <c><anno>Opts</anno></c> and
+ <p>
+ <c><anno>Module</anno></c>, <c><anno>Opts</anno></c>, and
<c><anno>Server</anno></c> have the same meanings
as when calling
- <seealso marker="#start_link/3">
- <c>gen_statem:start[_link]/3,4</c>.
- </seealso>
- However, the
- <seealso marker="#type-server_name">
- <c>server_name()</c>
- </seealso>
+ <seealso marker="#start_link/3"><c>start[_link]/3,4</c></seealso>.
+ However, the
+ <seealso marker="#type-server_name"><c>server_name()</c></seealso>
name must have been registered accordingly
<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>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>
+ <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.
</p>
<p>
- Failure: If the calling process was not started by a
- <seealso marker="proc_lib"><c>proc_lib</c></seealso>
+ The function fails 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
+ according to
<seealso marker="#type-server_name"><c>server_name()</c></seealso>.
</p>
</desc>
</func>
- </funcs>
+ <func>
+ <name name="reply" arity="1"/>
+ <name name="reply" arity="2"/>
+ <fsummary>Reply to a caller.</fsummary>
+ <desc>
+ <p>
+ This function can be used by a <c>gen_statem</c>
+ to explicitly send a reply to a process that waits in
+ <seealso marker="#call/2"><c>call/2</c></seealso>
+ when the reply cannot be defined in
+ the return value of a
+ <seealso marker="#state_function">state function</seealso>.
+ </p>
+ <p>
+ <c><anno>From</anno></c> must be the term from argument
+ <seealso marker="#type-event_type"><c>{call,<anno>From</anno>}</c></seealso>
+ to the
+ <seealso marker="#state_function">state function</seealso>.
+ <c><anno>From</anno></c> and <c><anno>Reply</anno></c>
+ can also be specified using a
+ <seealso marker="#type-reply_action"><c>reply_action()</c></seealso>
+ and multiple replies with a list of them.
+ </p>
+ <note>
+ <p>
+ A reply sent with this function is not visible
+ in <seealso marker="sys"><c>sys</c></seealso> debug output.
+ </p>
+ </note>
+ </desc>
+ </func>
+ <func>
+ <name name="start" arity="3"/>
+ <name name="start" arity="4"/>
+ <fsummary>Create a standalone <c>gen_statem</c> process.</fsummary>
+ <desc>
+ <p>
+ Creates a standalone <c>gen_statem</c> process according to
+ OTP design principles (using
+ <seealso marker="proc_lib"><c>proc_lib</c></seealso>
+ primitives).
+ As it does not get linked to the calling process,
+ this start function cannot be used by a supervisor
+ to start a child.
+ </p>
+ <p>
+ For a description of arguments and return values, see
+ <seealso marker="#start_link/3"><c>start_link/3,4</c></seealso>.
+ </p>
+ </desc>
+ </func>
+ <func>
+ <name name="start_link" arity="3"/>
+ <name name="start_link" arity="4"/>
+ <fsummary>Create a linked <c>gen_statem</c> process.</fsummary>
+ <desc>
+ <p>
+ Creates a <c>gen_statem</c> 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 <c>gen_statem</c> must be part of
+ a supervision tree so it gets linked to its supervisor.
+ </p>
+ <p>
+ The <c>gen_statem</c> process calls
+ <seealso marker="#Module:init/1"><c>Module:init/1</c></seealso>
+ to initialize the server. To ensure a synchronized startup
+ 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 <c>gen_statem</c>.
+ If the <c>gen_statem</c> is started with <c>start_link/3</c>,
+ no <c><anno>ServerName</anno></c> is provided and
+ the <c>gen_statem</c> 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 that is passed as
+ the argument to
+ <seealso marker="#Module:init/1"><c>Module:init/1</c></seealso>.
+ </p>
+ <list type="bulleted">
+ <item>
+ <p>
+ If option <c>{timeout,Time}</c> is present in
+ <c><anno>Opts</anno></c>, the <c>gen_statem</c>
+ is allowed to spend <c>Time</c> milliseconds initializing
+ or it terminates and the start function returns
+ <seealso marker="#type-start_ret"><c>{error,timeout}</c></seealso>.
+ </p>
+ </item>
+ <item>
+ <p>
+ If option
+ <seealso marker="#type-debug_opt"><c>{debug,Dbgs}</c></seealso>
+ is present in <c><anno>Opts</anno></c>, debugging through
+ <seealso marker="sys"><c>sys</c></seealso> is activated.
+ </p>
+ </item>
+ <item>
+ <p>
+ If option <c>{spawn_opt,SpawnOpts}</c> is present in
+ <c><anno>Opts</anno></c>, <c>SpawnOpts</c> is passed
+ as option list to
+ <seealso marker="erts:erlang#spawn_opt/2"><c>erlang:spawn_opt/2</c></seealso>,
+ which is used to spawn the <c>gen_statem</c> process.
+ </p>
+ </item>
+ </list>
+ <note>
+ <p>
+ Using spawn option <c>monitor</c> is not
+ allowed, it causes this function to fail with reason
+ <c>badarg</c>.
+ </p>
+ </note>
+ <p>
+ If the <c>gen_statem</c> is successfully created
+ and initialized, this function returns
+ <seealso marker="#type-start_ret"><c>{ok,Pid}</c></seealso>,
+ where <c>Pid</c> is the <c>pid()</c>
+ of the <c>gen_statem</c>.
+ If a process with the specified <c><anno>ServerName</anno></c>
+ exists already, this function returns
+ <seealso marker="#type-start_ret"><c>{error,{already_started,Pid}}</c></seealso>,
+ 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="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 <c>gen_statem</c>
+ <seealso marker="#type-server_ref"><c><anno>ServerRef</anno></c></seealso>
+ to exit with the specified <c><anno>Reason</anno></c>
+ and waits for it to terminate.
+ The <c>gen_statem</c> calls
+ <seealso marker="#Module:terminate/3"><c>Module:terminate/3</c></seealso>
+ 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> causes an
+ error report to be issued through
+ <seealso marker="kernel:error_logger#format/2"><c>error_logger:format/2</c></seealso>.
+ The default <c><anno>Reason</anno></c> is <c>normal</c>.
+ </p>
+ <p>
+ <c><anno>Timeout</anno></c> is an integer &gt; 0,
+ which specifies how many milliseconds to wait for the server to
+ terminate, or the atom <c>infinity</c> to wait indefinitely.
+ Defaults to <c>infinity</c>.
+ If the server does not terminate 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>
+ </funcs>
<section>
- <title>CALLBACK FUNCTIONS</title>
+ <title>Callback Functions</title>
<p>
- The following functions should be exported from a
+ The following functions are to be exported from a
<c>gen_statem</c> callback module.
</p>
</section>
+
<funcs>
+ <func>
+ <name>Module:code_change(OldVsn, OldState, OldData, 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 = {NewCallbackMode,NewState,NewData} | Reason</v>
+ <v>
+ NewCallbackMode =
+ <seealso marker="#type-callback_mode">callback_mode()</seealso>
+ </v>
+ <v>
+ OldState = NewState =
+ <seealso marker="#type-state">state()</seealso>
+ </v>
+ <v>
+ OldData = NewData =
+ <seealso marker="#type-data">data()</seealso>
+ </v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>
+ This function is called by a <c>gen_statem</c> when it is to
+ update its internal state during a release upgrade/downgrade,
+ that is, when the instruction <c>{update,Module,Change,...}</c>,
+ where <c>Change={advanced,Extra}</c>, is specified in the
+ <seealso marker="sasl:appup"><c>appup</c></seealso>
+ file. For more information, see
+ <seealso marker="doc/design_principles:release_handling#instr">OTP Design Principles</seealso>.
+ </p>
+ <p>
+ For an upgrade, <c>OldVsn</c> is <c>Vsn</c>, and
+ for 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>
+ <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>.
+ </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 must return the updated
+ internal state in an
+ <c>{NewCallbackMode,NewState,NewData}</c> tuple.
+ </p>
+ <p>
+ If the function returns <c>Reason</c>, the ongoing
+ upgrade fails and rolls back to the old release.</p>
+ <p>
+ This function can use
+ <seealso marker="erts:erlang#throw/1"><c>erlang:throw/1</c></seealso>
+ to return <c>Result</c> or <c>Reason</c>.
+ </p>
+ </desc>
+ </func>
<func>
<name>Module:init(Args) -> Result</name>
- <fsummary>Initialize process and internal state</fsummary>
+ <fsummary>Initialize process and internal state.</fsummary>
<type>
<v>Args = term()</v>
<v>Result = {CallbackMode,State,Data}</v>
@@ -1316,25 +1358,25 @@ handle_event(_, _, State, Data) ->
<v>Reason = term()</v>
</type>
<desc>
- <marker id="Module:init-1" />
- <p>
+ <marker id="Module:init-1"/>
+ <p>
Whenever a <c>gen_statem</c> is started using
- <seealso marker="#start_link/3"><c>start_link/3,4</c></seealso>
+ <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
+ <seealso marker="#start/3"><c>start/3,4</c></seealso>,
+ this function is called by the new process to initialize
the implementation state and server data.
</p>
- <p>
+ <p>
<c>Args</c> is the <c>Args</c> argument provided to the start
- function.
+ function.
</p>
- <p>
- If the initialization is successful, the function should
- return <c>{CallbackMode,State,Data}</c> or
+ <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>.
+ <seealso marker="#type-callback_mode"><em>callback mode</em></seealso>
of the <c>gen_statem</c>.
<c>State</c> is the initial
<seealso marker="#type-state"><c>state()</c></seealso>
@@ -1347,28 +1389,127 @@ handle_event(_, _, State, Data) ->
<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
+ <p>
+ If the initialization fails,
+ the function is to return <c>{stop,Reason}</c>
+ or <c>ignore</c>; see
<seealso marker="#start_link/3"><c>start_link/3,4</c></seealso>.
</p>
<p>
- This function may use
- <seealso marker="erts:erlang#throw/1"><c>throw/1</c></seealso>
+ This function can use
+ <seealso marker="erts:erlang#throw/1"><c>erlang:throw/1</c></seealso>
to return <c>Result</c>.
</p>
</desc>
</func>
<func>
+ <name>Module:format_status(Opt, [PDict,State,Data]) ->
+ Status
+ </name>
+ <fsummary>Optional function for providing a term describing the
+ current <c>gen_statem</c> status.</fsummary>
+ <type>
+ <v>Opt = normal | terminate</v>
+ <v>PDict = [{Key, Value}]</v>
+ <v>
+ State =
+ <seealso marker="#type-state">state()</seealso>
+ </v>
+ <v>
+ Data =
+ <seealso marker="#type-data">data()</seealso>
+ </v>
+ <v>Key = term()</v>
+ <v>Value = term()</v>
+ <v>Status = term()</v>
+ </type>
+ <desc>
+ <note>
+ <p>
+ This callback is optional, so a callback module does not need
+ to export it. The <c>gen_statem</c> module provides a default
+ implementation of this function that returns
+ <c>{State,Data}</c>. If this callback fails, the default
+ function returns <c>{State,Info}</c>,
+ where <c>Info</c> informs of the crash but no details,
+ to hide possibly sensitive data.
+ </p>
+ </note>
+ <p>This function is called by a <c>gen_statem</c> process when
+ any of the following apply:</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 <c>gen_statem</c> status. <c>Opt</c> is set
+ to the atom <c>normal</c> for this case.
+ </item>
+ <item>
+ The <c>gen_statem</c> 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 changing the form and
+ appearance of the <c>gen_statem</c> status for these cases. A
+ callback module wishing to change the
+ <seealso marker="sys#get_status/1"><c>sys:get_status/1,2</c></seealso>
+ return value and how
+ its status appears in termination error logs exports an
+ instance of <c>format_status/2</c>, which returns a term
+ describing the current status of the <c>gen_statem</c>.
+ </p>
+ <p>
+ <c>PDict</c> is the current value of the process dictionary
+ of the <c>gen_statem</c>.
+ </p>
+ <p>
+ <seealso marker="#type-state"><c>State</c></seealso>
+ is the internal state of the <c>gen_statem</c>.
+ </p>
+ <p>
+ <seealso marker="#type-data"><c>Data</c></seealso>
+ is the internal server data of the <c>gen_statem</c>.
+ </p>
+ <p>
+ The function is to return <c>Status</c>, a term that
+ changes the details of the current state and status of
+ the <c>gen_statem</c>. There are no restrictions on the
+ form <c>Status</c> can take, but for the
+ <seealso marker="sys#get_status/1"><c>sys:get_status/1,2</c></seealso>
+ 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 <c>gen_statem</c> state. Following this recommendation is not
+ required, but it makes the callback module status
+ consistent with the rest of the
+ <seealso marker="sys#get_status/1"><c>sys:get_status/1,2</c></seealso>
+ return value.
+ </p>
+ <p>
+ One use for this function is to return compact alternative
+ state representations to avoid having large state terms
+ printed in log files. Another use is to hide sensitive data from
+ being written to the error log.
+ </p>
+ <p>
+ This function can use
+ <seealso marker="erts:erlang#throw/1"><c>erlang:throw/1</c></seealso>
+ to return <c>Status</c>.
+ </p>
+ </desc>
+ </func>
+
+ <func>
<name>Module:StateName(EventType, EventContent, Data) ->
- StateFunctionResult
+ StateFunctionResult
</name>
<name>Module:handle_event(EventType, EventContent,
- State, Data) -> HandleEventResult
+ State, Data) -> HandleEventResult
</name>
- <fsummary>Handle an event</fsummary>
+ <fsummary>Handle an event.</fsummary>
<type>
<v>
EventType =
@@ -1385,59 +1526,55 @@ handle_event(_, _, State, Data) ->
</v>
<v>
StateFunctionResult =
- <seealso marker="#type-state_function_result">
- state_function_result()
- </seealso>
+ <seealso marker="#type-state_function_result">state_function_result()</seealso>
</v>
<v>
HandleEventResult =
- <seealso marker="#type-handle_event_result">
- handle_event_result()
- </seealso>
+ <seealso marker="#type-handle_event_result">handle_event_result()</seealso>
</v>
</type>
<desc>
- <p>
+ <p>
Whenever a <c>gen_statem</c> receives an event from
- <seealso marker="#call/2"><c>call/2</c></seealso>,
- <seealso marker="#cast/2"><c>cast/2</c></seealso> or
- as a normal process message one of these functions is called. If
+ <seealso marker="#call/2"><c>call/2</c></seealso>,
+ <seealso marker="#cast/2"><c>cast/2</c></seealso>, or
+ as a normal process message, one of these functions is called. If
<seealso marker="#type-callback_mode"><em>callback mode</em></seealso>
- is <c>state_functions</c> then <c>Module:StateName/3</c> is called,
- and if it is <c>handle_event_function</c>
- then <c>Module:handle_event/4</c> is called.
+ is <c>state_functions</c>, <c>Module:StateName/3</c> is called,
+ and if it is <c>handle_event_function</c>,
+ <c>Module:handle_event/4</c> is called.
</p>
<p>
If <c>EventType</c> is
- <seealso marker="#type-event_type"><c>{call,From}</c></seealso>
- the caller is waiting for a reply. The reply can be sent
+ <seealso marker="#type-event_type"><c>{call,From}</c></seealso>,
+ the caller waits 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,From,Reply}</c> in
<seealso marker="#type-action"><c>Actions</c></seealso>, in
- <seealso marker="#type-reply_action"><c>Replies</c></seealso>
+ <seealso marker="#type-reply_action"><c>Replies</c></seealso>,
or by calling
<seealso marker="#reply/2"><c>reply(From, Reply)</c></seealso>.
</p>
<p>
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 next state.
+ does not match equal (<c>=/=</c>) to the current state,
+ all postponed events are 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>
+ the next state must be an atom, but for <c>HandleEventResult</c>
there is no restriction on the next state.
</p>
<p>
- See <seealso marker="#type-action"><c>action()</c></seealso>
- for options that can be set and actions that can be done
- by <c>gen_statem</c> after returning from this function.
+ For options that can be set and actions that can be done
+ by <c>gen_statem</c> after returning from this function,
+ see <seealso marker="#type-action"><c>action()</c></seealso>.
</p>
<p>
- These functions may use
- <seealso marker="erts:erlang#throw/1"><c>throw/1</c></seealso>,
+ These functions can use
+ <seealso marker="erts:erlang#throw/1"><c>erlang:throw/1</c></seealso>,
to return the result.
</p>
</desc>
@@ -1445,7 +1582,7 @@ handle_event(_, _, State, Data) ->
<func>
<name>Module:terminate(Reason, State, Data) -> Ignored</name>
- <fsummary>Clean up before termination</fsummary>
+ <fsummary>Clean up before termination.</fsummary>
<type>
<v>Reason = normal | shutdown | {shutdown,term()} | term()</v>
<v>State = <seealso marker="#type-state">state()</seealso></v>
@@ -1453,272 +1590,82 @@ handle_event(_, _, State, Data) ->
<v>Ignored = term()</v>
</type>
<desc>
- <p>
+ <p>
This function is called by a <c>gen_statem</c>
- when it is about to terminate. It should be the opposite of
+ when it is about to terminate. It is to 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 <c>gen_statem</c> terminates with <c>Reason</c>. The return
- value is ignored.</p>
- <p>
+ and do any necessary cleaning up. When it returns,
+ the <c>gen_statem</c> 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"><c>State</c></seealso>
+ <seealso marker="#type-state"><c>State</c></seealso>
is the internal state of the <c>gen_statem</c>.
</p>
- <p>
+ <p>
<c>Reason</c> depends on why the <c>gen_statem</c>
is terminating.
- If it is because another callback function has returned a
- stop tuple <c>{stop,Reason}</c> in
+ If it is because another callback function has returned, a
+ stop tuple <c>{stop,Reason}</c> in
<seealso marker="#type-action"><c>Actions</c></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.
+ <c>Reason</c> has the value specified in that tuple.
+ If it is because of a failure, <c>Reason</c> is the error reason.
</p>
<p>
If the <c>gen_statem</c> 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
+ ordered by its supervisor to terminate, this function is
+ called with <c>Reason = shutdown</c> if both the following
conditions apply:</p>
<list type="bulleted">
<item>
- the <c>gen_statem</c> has been set
- to trap exit signals, and
+ <p>
+ The <c>gen_statem</c> has been set
+ to trap exit signals.
+ </p>
</item>
<item>
- the shutdown strategy as defined in the supervisor's
- child specification is an integer timeout value, not
- <c>brutal_kill</c>.
+ <p>
+ The shutdown strategy as defined in the supervisor's
+ child specification is an integer time-out value, not
+ <c>brutal_kill</c>.
+ </p>
</item>
</list>
<p>
Even if the <c>gen_statem</c> is <em>not</em>
- part of a supervision tree, this function will be called
+ part of a supervision tree, this function is called
if it receives an <c>'EXIT'</c> message from its parent.
- <c>Reason</c> will be the same as
+ <c>Reason</c> is the same as
in the <c>'EXIT'</c> message.
</p>
<p>
- Otherwise, the <c>gen_statem</c> will be immediately terminated.
+ Otherwise, the <c>gen_statem</c> is immediately terminated.
</p>
<p>
- Note that for any other reason than <c>normal</c>,
- <c>shutdown</c>, or <c>{shutdown,Term}</c>
- the <c>gen_statem</c> is assumed to terminate due to an error
+ Notice that for any other reason than <c>normal</c>,
+ <c>shutdown</c>, or <c>{shutdown,Term}</c>,
+ the <c>gen_statem</c> is assumed to terminate because of an error
and an error report is issued using
- <seealso marker="kernel:error_logger#format/2">
- <c>error_logger:format/2</c>.
- </seealso>
+ <seealso marker="kernel:error_logger#format/2"><c>error_logger:format/2</c></seealso>.
</p>
<p>
- This function may use
- <seealso marker="erts:erlang#throw/1"><c>throw/1</c></seealso>
+ This function can use
+ <seealso marker="erts:erlang#throw/1"><c>erlang:throw/1</c></seealso>
to return <c>Ignored</c>, which is ignored anyway.
</p>
</desc>
</func>
-
- <func>
- <name>Module:code_change(OldVsn, OldState, OldData, 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 = {NewCallbackMode,NewState,NewData} | Reason</v>
- <v>
- NewCallbackMode =
- <seealso marker="#type-callback_mode">callback_mode()</seealso>
- </v>
- <v>
- OldState = NewState =
- <seealso marker="#type-state">state()</seealso>
- </v>
- <v>
- OldData = NewData =
- <seealso marker="#type-data">data()</seealso>
- </v>
- <v>Reason = term()</v>
- </type>
- <desc>
- <p>
- This function is called by a <c>gen_statem</c> when it should
- update its internal state during a release upgrade/downgrade,
- that is when the instruction <c>{update,Module,Change,...}</c>
- where <c>Change={advanced,Extra}</c> is given in the
- <seealso marker="sasl:appup"><c>appup</c></seealso>
- 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>
- <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
- since the new code surely knows what <em>callback mode</em>
- it needs, but for a downgrade this function will have to
- know from the <c>Extra</c> argument that comes from the
- <seealso marker="sasl:appup"><c>appup</c></seealso>
- file what <em>callback mode</em> the old code did use.
- It may also be possible to figure this out
- from the <c>{down,Vsn}</c> argument since <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>.
- </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>{NewCallbackMode,NewState,NewData}</c> tuple.
- </p>
- <p>
- If the function returns <c>Reason</c>, the ongoing
- upgrade will fail and roll back to the old release.</p>
- <p>
- This function may use
- <seealso marker="erts:erlang#throw/1"><c>throw/1</c></seealso>
- to return <c>Result</c> or <c>Reason</c>.
- </p>
- </desc>
- </func>
-
- <func>
- <name>Module:format_status(Opt, [PDict,State,Data]) ->
- Status
- </name>
- <fsummary>Optional function for providing a term describing the
- current <c>gen_statem</c> status</fsummary>
- <type>
- <v>Opt = normal | terminate</v>
- <v>PDict = [{Key, Value}]</v>
- <v>
- State =
- <seealso marker="#type-state">state()</seealso>
- </v>
- <v>
- Data =
- <seealso marker="#type-data">data()</seealso>
- </v>
- <v>Key = term()</v>
- <v>Value = term()</v>
- <v>Status = term()</v>
- </type>
- <desc>
- <note>
- <p>
- This callback is optional, so a callback module need not
- export it. The <c>gen_statem</c> module provides a default
- implementation of this function that returns
- <c>{State,Data}</c>. If this callback fails the default
- function will return <c>{State,Info}</c>
- where <c>Info</c> informs of the crash but no details,
- to hide possibly sensitive data.
- </p>
- </note>
- <p>This function is called by a <c>gen_statem</c> 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 <c>gen_statem</c> status. <c>Opt</c> is set
- to the atom <c>normal</c> for this case.
- </item>
- <item>
- The <c>gen_statem</c> 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 <c>gen_statem</c> 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 <c>gen_statem</c>.
- </p>
- <p>
- <c>PDict</c> is the current value of the <c>gen_statem</c>'s
- process dictionary.
- </p>
- <p>
- <seealso marker="#type-state"><c>State</c></seealso>
- is the internal state of the <c>gen_statem</c>.
- </p>
- <p>
- <seealso marker="#type-data"><c>Data</c></seealso>
- is the internal server data of the <c>gen_statem</c>.
- </p>
- <p>
- The function should return <c>Status</c>, a term that
- customises the details of the current state and status of
- the <c>gen_statem</c>. There are no restrictions on the
- form <c>Status</c> can take, but for the
- <seealso marker="sys#get_status/1">
- <c>sys:get_status/1,2</c>
- </seealso>
- 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 <c>gen_statem</c> 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. Another is to hide sensitive data from
- being written to the error log.
- </p>
- <p>
- This function may use
- <seealso marker="erts:erlang#throw/1"><c>throw/1</c></seealso>
- to return <c>Status</c>.
- </p>
- </desc>
- </func>
-
</funcs>
<section>
- <title>SEE ALSO</title>
- <p><seealso marker="gen_event"><c>gen_event(3)</c></seealso>,
+ <title>See Also</title>
+ <p>
+ <seealso marker="gen_event"><c>gen_event(3)</c></seealso>,
<seealso marker="gen_fsm"><c>gen_fsm(3)</c></seealso>,
<seealso marker="gen_server"><c>gen_server(3)</c></seealso>,
- <seealso marker="supervisor"><c>supervisor(3)</c></seealso>,
<seealso marker="proc_lib"><c>proc_lib(3)</c></seealso>,
- <seealso marker="sys"><c>sys(3)</c></seealso></p>
+ <seealso marker="supervisor"><c>supervisor(3)</c></seealso>,
+ <seealso marker="sys"><c>sys(3)</c></seealso>.
+ </p>
</section>
</erlref>
diff --git a/lib/stdlib/doc/src/proc_lib.xml b/lib/stdlib/doc/src/proc_lib.xml
index 245580b1ba..f02b1f0651 100644
--- a/lib/stdlib/doc/src/proc_lib.xml
+++ b/lib/stdlib/doc/src/proc_lib.xml
@@ -73,6 +73,13 @@
<name name="priority_level"/>
</datatype>
<datatype>
+ <name name="max_heap_size"/>
+ <desc>
+ <p>See <seealso marker="erts:erlang#process_flag_max_heap_size">
+ erlang:process_flag(max_heap_size, MaxHeapSize)</seealso>.</p>
+ </desc>
+ </datatype>
+ <datatype>
<name name="dict_or_pid"/>
</datatype>
</datatypes>
diff --git a/lib/stdlib/doc/src/sofs.xml b/lib/stdlib/doc/src/sofs.xml
index cf0855bc85..1e5be367bd 100644
--- a/lib/stdlib/doc/src/sofs.xml
+++ b/lib/stdlib/doc/src/sofs.xml
@@ -399,8 +399,7 @@ fun(S) -> sofs:partition(1, S) end
<datatype>
<!-- Parameterized opaque types are NYI: -->
<name>tuple_of(T)</name>
- <desc><p><marker id="type-tuple_of"/>
- A tuple where the elements are of type <c>T</c>.</p></desc>
+ <desc><p>A tuple where the elements are of type <c>T</c>.</p></desc>
</datatype>
</datatypes>
<funcs>
diff --git a/lib/stdlib/src/beam_lib.erl b/lib/stdlib/src/beam_lib.erl
index 7a17226e46..fe9df601eb 100644
--- a/lib/stdlib/src/beam_lib.erl
+++ b/lib/stdlib/src/beam_lib.erl
@@ -46,7 +46,7 @@
terminate/2,code_change/3]).
-export([make_crypto_key/2, get_crypto_key/1]). %Utilities used by compiler
--export_type([attrib_entry/0, compinfo_entry/0, labeled_entry/0]).
+-export_type([attrib_entry/0, compinfo_entry/0, labeled_entry/0, label/0]).
-import(lists, [append/1, delete/2, foreach/2, keysort/2,
member/2, reverse/1, sort/1, splitwith/2]).
diff --git a/lib/stdlib/src/epp.erl b/lib/stdlib/src/epp.erl
index 55a818e87c..73934e0e3c 100644
--- a/lib/stdlib/src/epp.erl
+++ b/lib/stdlib/src/epp.erl
@@ -53,6 +53,8 @@
| {atom(),non_neg_integer()}
| tokens().
+-type warning_info() :: {erl_anno:location(), module(), term()}.
+
-define(DEFAULT_ENCODING, utf8).
%% Epp state record.
@@ -158,11 +160,13 @@ scan_erl_form(Epp) ->
epp_request(Epp, scan_erl_form).
-spec parse_erl_form(Epp) ->
- {'ok', AbsForm} | {'eof', Line} | {error, ErrorInfo} when
+ {'ok', AbsForm} | {error, ErrorInfo} |
+ {'warning',WarningInfo} | {'eof',Line} when
Epp :: epp_handle(),
AbsForm :: erl_parse:abstract_form(),
Line :: erl_anno:line(),
- ErrorInfo :: erl_scan:error_info() | erl_parse:error_info().
+ ErrorInfo :: erl_scan:error_info() | erl_parse:error_info(),
+ WarningInfo :: warning_info().
parse_erl_form(Epp) ->
case epp_request(Epp, scan_erl_form) of
@@ -219,6 +223,10 @@ format_error({illegal_function_usage,Macro}) ->
io_lib:format("?~s must not begin a form", [Macro]);
format_error({'NYI',What}) ->
io_lib:format("not yet implemented '~s'", [What]);
+format_error({error,Term}) ->
+ io_lib:format("-error(~p).", [Term]);
+format_error({warning,Term}) ->
+ io_lib:format("-warning(~p).", [Term]);
format_error(E) -> file:format_error(E).
-spec parse_file(FileName, IncludePath, PredefMacros) ->
@@ -263,9 +271,11 @@ parse_file(Ifile, Options) ->
-spec parse_file(Epp) -> [Form] when
Epp :: epp_handle(),
- Form :: erl_parse:abstract_form() | {'error', ErrorInfo} | {'eof',Line},
+ Form :: erl_parse:abstract_form() | {'error', ErrorInfo} |
+ {'warning',WarningInfo} | {'eof',Line},
Line :: erl_anno:line(),
- ErrorInfo :: erl_scan:error_info() | erl_parse:error_info().
+ ErrorInfo :: erl_scan:error_info() | erl_parse:error_info(),
+ WarningInfo :: warning_info().
parse_file(Epp) ->
case parse_erl_form(Epp) of
@@ -273,6 +283,8 @@ parse_file(Epp) ->
[Form|parse_file(Epp)];
{error,E} ->
[{error,E}|parse_file(Epp)];
+ {warning,W} ->
+ [{warning,W}|parse_file(Epp)];
{eof,Location} ->
[{eof,erl_anno:new(Location)}]
end.
@@ -752,6 +764,10 @@ scan_toks([{'-',_Lh},{atom,_Ld,define}=Define|Toks], From, St) ->
scan_define(Toks, Define, From, St);
scan_toks([{'-',_Lh},{atom,_Ld,undef}=Undef|Toks], From, St) ->
scan_undef(Toks, Undef, From, St);
+scan_toks([{'-',_Lh},{atom,_Ld,error}=Error|Toks], From, St) ->
+ scan_err_warn(Toks, Error, From, St);
+scan_toks([{'-',_Lh},{atom,_Ld,warning}=Warn|Toks], From, St) ->
+ scan_err_warn(Toks, Warn, From, St);
scan_toks([{'-',_Lh},{atom,_Li,include}=Inc|Toks], From, St) ->
scan_include(Toks, Inc, From, St);
scan_toks([{'-',_Lh},{atom,_Li,include_lib}=IncLib|Toks], From, St) ->
@@ -807,6 +823,24 @@ scan_extends([{atom,Ln,A}=ModAtom,{')',_Lr}|_Ts], Ms0) ->
Ms#{'BASE_MODULE_STRING':={none,[{string,Ln,ModString}]}};
scan_extends(_Ts, Ms) -> Ms.
+scan_err_warn([{'(',_}|_]=Toks0, {atom,_,Tag}=Token, From, St) ->
+ try expand_macros(Toks0, St) of
+ Toks when is_list(Toks) ->
+ case erl_parse:parse_term(Toks) of
+ {ok,Term} ->
+ epp_reply(From, {Tag,{loc(Token),epp,{Tag,Term}}});
+ {error,_} ->
+ epp_reply(From, {error,{loc(Token),epp,{bad,Tag}}})
+ end
+ catch
+ _:_ ->
+ epp_reply(From, {error,{loc(Token),epp,{bad,Tag}}})
+ end,
+ wait_req_scan(St);
+scan_err_warn(_Toks, {atom,_,Tag}=Token, From, St) ->
+ epp_reply(From, {error,{loc(Token),epp,{bad,Tag}}}),
+ wait_req_scan(St).
+
%% scan_define(Tokens, DefineToken, From, EppState)
scan_define([{'(',_Lp},{Type,_Lm,_}=Mac|Toks], Def, From, St)
@@ -933,9 +967,15 @@ scan_include(_Toks, Inc, From, St) ->
%% normal search path, if not we assume that the first directory name
%% is a library name, find its true directory and try with that.
-find_lib_dir(NewName) ->
- [Lib | Rest] = filename:split(NewName),
- {code:lib_dir(list_to_atom(Lib)), Rest}.
+expand_lib_dir(Name) ->
+ try
+ [App|Path] = filename:split(Name),
+ LibDir = code:lib_dir(list_to_atom(App)),
+ {ok,fname_join([LibDir|Path])}
+ catch
+ _:_ ->
+ error
+ end.
scan_include_lib([{'(',_Llp},{string,_Lf,_NewName0},{')',_Lrp},{dot,_Ld}],
Inc, From, St)
@@ -950,12 +990,11 @@ scan_include_lib([{'(',_Llp},{string,_Lf,NewName0},{')',_Lrp},{dot,_Ld}],
{ok,NewF,Pname} ->
wait_req_scan(enter_file2(NewF, Pname, From, St, Loc));
{error,_E1} ->
- case catch find_lib_dir(NewName) of
- {LibDir, Rest} when is_list(LibDir) ->
- LibName = fname_join([LibDir | Rest]),
- case file:open(LibName, [read]) of
+ case expand_lib_dir(NewName) of
+ {ok,Header} ->
+ case file:open(Header, [read]) of
{ok,NewF} ->
- wait_req_scan(enter_file2(NewF, LibName, From,
+ wait_req_scan(enter_file2(NewF, Header, From,
St, Loc));
{error,_E2} ->
epp_reply(From,
@@ -963,7 +1002,7 @@ scan_include_lib([{'(',_Llp},{string,_Lf,NewName0},{')',_Lrp},{dot,_Ld}],
{include,lib,NewName}}}),
wait_req_scan(St)
end;
- _Error ->
+ error ->
epp_reply(From, {error,{loc(Inc),epp,
{include,lib,NewName}}}),
wait_req_scan(St)
diff --git a/lib/stdlib/src/erl_compile.erl b/lib/stdlib/src/erl_compile.erl
index ef54076ee3..a6ae398d03 100644
--- a/lib/stdlib/src/erl_compile.erl
+++ b/lib/stdlib/src/erl_compile.erl
@@ -60,6 +60,7 @@ compile_cmdline() ->
_ -> my_halt(2)
end.
+-spec my_halt(_) -> no_return().
my_halt(Reason) ->
erlang:halt(Reason).
diff --git a/lib/stdlib/src/escript.erl b/lib/stdlib/src/escript.erl
index b8ce311c35..f53b0e2246 100644
--- a/lib/stdlib/src/escript.erl
+++ b/lib/stdlib/src/escript.erl
@@ -906,6 +906,7 @@ anno(L) ->
fatal(Str) ->
throw(Str).
+-spec my_halt(_) -> no_return().
my_halt(Reason) ->
erlang:halt(Reason).
diff --git a/lib/stdlib/src/gen_statem.erl b/lib/stdlib/src/gen_statem.erl
index f9e2e5f7d2..23bddafeed 100644
--- a/lib/stdlib/src/gen_statem.erl
+++ b/lib/stdlib/src/gen_statem.erl
@@ -97,7 +97,7 @@
%% * Postponing the current event is performed
%% iff 'postpone' is 'true'.
%% * A state timer is started iff 'timeout' is set.
- %% * Pending events are processed or if there are
+ %% * Pending events are handled or if there are
%% no pending events the server goes into receive
%% or hibernate (iff 'hibernate' is 'true')
%%
@@ -282,16 +282,6 @@ event_type(Type) ->
STACKTRACE(),
try throw(ok) catch _ -> erlang:get_stacktrace() end).
--define(
- TERMINATE(Class, Reason, Debug, S, Q),
- terminate(
- begin Class end,
- begin Reason end,
- ?STACKTRACE(),
- begin Debug end,
- begin S end,
- begin Q end)).
-
%%%==========================================================================
%%% API
@@ -300,11 +290,11 @@ event_type(Type) ->
| {'via', RegMod :: module(), Name :: term()}
| {'local', atom()}.
-type server_ref() ::
- {'global', GlobalName :: term()}
- | {'via', RegMod :: module(), ViaName :: term()}
+ pid()
| (LocalName :: atom())
| {Name :: atom(), Node :: atom()}
- | pid().
+ | {'global', GlobalName :: term()}
+ | {'via', RegMod :: module(), ViaName :: term()}.
-type debug_opt() ::
{'debug',
Dbgs ::
@@ -523,12 +513,15 @@ send(Proc, Msg) ->
ok
end.
-%% Here init_it/6 and enter_loop/5,6,7 functions converge
+%% Here the init_it/6 and enter_loop/5,6,7 functions converge
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),
- PrevState = make_ref(), % Will be discarded by loop_event_actions/9
+ P = Events = [],
+ Event = {internal,initial_state},
+ %% We enforce {postpone,false} to ensure that
+ %% our fake Event gets discarded, thought it might get logged
NewActions =
if
is_list(Actions) ->
@@ -540,15 +533,17 @@ enter(Module, Opts, CallbackMode, State, Data, Server, Actions, Parent) ->
callback_mode => CallbackMode,
module => Module,
name => Name,
- state => PrevState,
+ %% All fields below will be replaced according to the arguments to
+ %% loop_event_actions/10 when it finally loops back to loop/3
+ state => State,
data => Data,
- timer => undefined,
- postponed => [],
- hibernate => false},
+ postponed => P,
+ hibernate => false,
+ timer => undefined},
+ NewDebug = sys_debug(Debug, S, State, {enter,Event,State}),
loop_event_actions(
- Parent, Debug, S, [],
- {event,undefined}, % Will be discarded thanks to {postpone,false}
- PrevState, State, Data, NewActions).
+ Parent, NewDebug, S, Events,
+ State, Data, P, Event, State, NewActions).
%%%==========================================================================
%%% gen callbacks
@@ -617,8 +612,12 @@ init_result(Starter, Parent, ServerRef, Module, Result, Opts) ->
system_continue(Parent, Debug, S) ->
loop(Parent, Debug, S).
-system_terminate(Reason, _Parent, Debug, S) ->
- ?TERMINATE(exit, Reason, Debug, S, []).
+system_terminate(
+ Reason, _Parent, Debug,
+ #{state := State, data := Data, postponed := P} = S) ->
+ terminate(
+ exit, Reason, ?STACKTRACE(),
+ Debug, S, [], State, Data, P).
system_code_change(
#{module := Module,
@@ -634,7 +633,10 @@ system_code_change(
{NewCallbackMode,NewState,NewData} ->
callback_mode(NewCallbackMode) orelse
error({callback_mode,NewCallbackMode}),
- {ok,S#{state := NewState, data := NewData}};
+ {ok,
+ S#{callback_mode := NewCallbackMode,
+ state := NewState,
+ data := NewData}};
{ok,_} = Error ->
error({case_clause,Error});
Error ->
@@ -654,7 +656,7 @@ system_replace_state(
format_status(
Opt,
[PDict,SysState,Parent,Debug,
- #{name := Name, postponed := P} = S]) ->
+ #{name := Name, postponed := P, state := State, data := Data} = S]) ->
Header = gen:format_status_header("Status for state machine", Name),
Log = sys:get_debug(log, Debug, []),
[{header,Header},
@@ -663,7 +665,7 @@ format_status(
{"Parent",Parent},
{"Logged Events",Log},
{"Postponed",P}]} |
- case format_status(Opt, PDict, S) of
+ case format_status(Opt, PDict, S, State, Data) of
L when is_list(L) -> L;
T -> [T]
end].
@@ -673,21 +675,21 @@ format_status(
%% them, not as the real erlang messages. Use trace for that.
%%---------------------------------------------------------------------------
-print_event(Dev, {in,Event}, #{name := Name}) ->
+print_event(Dev, {in,Event}, {Name,_}) ->
io:format(
Dev, "*DBG* ~p received ~s~n",
[Name,event_string(Event)]);
-print_event(Dev, {out,Reply,{To,_Tag}}, #{name := Name}) ->
+print_event(Dev, {out,Reply,{To,_Tag}}, {Name,_}) ->
io:format(
Dev, "*DBG* ~p sent ~p to ~p~n",
[Name,Reply,To]);
-print_event(Dev, {Tag,Event,NewState}, #{name := Name, state := State}) ->
+print_event(Dev, {Tag,Event,NextState}, {Name,State}) ->
StateString =
- case NewState of
+ case NextState of
State ->
io_lib:format("~p", [State]);
_ ->
- io_lib:format("~p => ~p", [State,NewState])
+ io_lib:format("~p => ~p", [State,NextState])
end,
io:format(
Dev, "*DBG* ~p ~w ~s in state ~s~n",
@@ -697,16 +699,17 @@ event_string(Event) ->
case Event of
{{call,{Pid,_Tag}},Request} ->
io_lib:format("call ~p from ~w", [Request,Pid]);
- {Tag,Content} ->
- io_lib:format("~w ~p", [Tag,Content])
+ {EventType,EventContent} ->
+ io_lib:format("~w ~p", [EventType,EventContent])
end.
-sys_debug(Debug, S, Entry) ->
+sys_debug(Debug, #{name := Name}, State, Entry) ->
case Debug of
[] ->
Debug;
_ ->
- sys:handle_debug(Debug, fun print_event/3, S, Entry)
+ sys:handle_debug(
+ Debug, fun print_event/3, {Name,State}, Entry)
end.
%%%==========================================================================
@@ -720,7 +723,7 @@ wakeup_from_hibernate(Parent, Debug, S) ->
%%% State Machine engine implementation of proc_lib/gen server
%% Server loop, consists of all loop* functions
-%% and some detours through sys and proc_lib
+%% and detours through sys:handle_system_message/7 and proc_lib:hibernate/3
%% Entry point for system_continue/3
loop(Parent, Debug, #{hibernate := Hibernate} = S) ->
@@ -749,12 +752,16 @@ loop_receive(Parent, Debug, #{timer := Timer} = S) ->
sys:handle_system_msg(
Req, Pid, Parent, ?MODULE, Debug, S, Hibernate);
{'EXIT',Parent,Reason} = EXIT ->
+ #{state := State, data := Data, postponed := P} = S,
%% EXIT is not a 2-tuple and therefore
%% not an event and has no event_type(),
%% but this will stand out in the crash report...
- ?TERMINATE(exit, Reason, Debug, S, [EXIT]);
+ terminate(
+ exit, Reason, ?STACKTRACE(),
+ Debug, S, [EXIT], State, Data, P);
{timeout,Timer,Content} when Timer =/= undefined ->
- loop_event(Parent, Debug, S, {timeout,Content});
+ loop_receive_result(
+ Parent, Debug, S, {timeout,Content});
_ ->
%% Cancel Timer if running
case Timer of
@@ -782,30 +789,81 @@ loop_receive(Parent, Debug, #{timer := Timer} = S) ->
_ ->
{info,Msg}
end,
- loop_event(Parent, Debug, S, Event)
+ loop_receive_result(Parent, Debug, S, Event)
end
end.
-loop_event(Parent, Debug, S, Event) ->
- %% The timer field and the hibernate flag in S
- %% are now invalid and ignored until we get back to loop/3
- NewDebug = sys_debug(Debug, S, {in,Event}),
- %% Here the queue of not yet processed events is created
- loop_events(Parent, NewDebug, S, [Event], false).
-
-%% Process first the event queue, or if it is empty
-%% loop back to receive a new event
-loop_events(Parent, Debug, S, [], _Hibernate) ->
- loop(Parent, Debug, S);
+loop_receive_result(
+ Parent, Debug,
+ #{state := State,
+ data := Data,
+ postponed := P} = S,
+ Event) ->
+ %% The engine state map S is now dismantled
+ %% and will not be restored until we return to loop/3.
+ %%
+ %% The fields 'callback_mode', 'module', and 'name' are still valid.
+ %% The fields 'state', 'data', and 'postponed' are held in arguments.
+ %% The fields 'timer' and 'hibernate' will be recalculated.
+ %%
+ NewDebug = sys_debug(Debug, S, State, {in,Event}),
+ %% Here the queue of not yet handled events is created
+ Events = [],
+ Hibernate = false,
+ loop_event(
+ Parent, NewDebug, S, Events, State, Data, P, Event, Hibernate).
+
+%% Process the event queue, or if it is empty
+%% loop back to loop/3 to receive a new event
+loop_events(
+ Parent, Debug, S, [Event|Events],
+ State, Data, P, Hibernate, _Timeout) ->
+ %%
+ %% If there was a state timer requested we just ignore that
+ %% since we have events to handle which cancels the timer
+ loop_event(
+ Parent, Debug, S, Events, State, Data, P, Event, Hibernate);
loop_events(
+ Parent, Debug, S, [],
+ State, Data, P, Hibernate, Timeout) ->
+ case Timeout of
+ {timeout,0,EventContent} ->
+ %% Immediate timeout - simulate it
+ %% so we do not get the timeout message
+ %% after any received event
+ loop_event(
+ Parent, Debug, S, [],
+ State, Data, P, {timeout,EventContent}, Hibernate);
+ {timeout,Time,EventContent} ->
+ %% Actually start a timer
+ Timer = erlang:start_timer(Time, self(), EventContent),
+ loop_events_done(
+ Parent, Debug, S, Timer, State, Data, P, Hibernate);
+ undefined ->
+ %% No state timeout has been requested
+ Timer = undefined,
+ loop_events_done(
+ Parent, Debug, S, Timer, State, Data, P, Hibernate)
+ end.
+%%
+loop_events_done(Parent, Debug, S, Timer, State, Data, P, Hibernate) ->
+ NewS =
+ S#{
+ state := State,
+ data := Data,
+ postponed := P,
+ hibernate := Hibernate,
+ timer := Timer},
+ loop(Parent, Debug, NewS).
+
+loop_event(
Parent, Debug,
#{callback_mode := CallbackMode,
- module := Module,
- state := State,
- data := Data} = S,
- [{Type,Content} = Event|Events] = Q,
- Hibernate) ->
- %% If the Hibernate flag is true here it can only be
+ module := Module} = S,
+ Events,
+ State, Data, P, {Type,Content} = Event, Hibernate) ->
+ %%
+ %% If Hibernate is true here it can only be
%% because it was set from an event action
%% and we did not go into hibernation since there
%% were events in queue, so we do what the user
@@ -813,6 +871,7 @@ loop_events(
%% would have happened if we actually hibernated
%% and immediately was awakened
Hibernate andalso garbage_collect(),
+ %%
try
case CallbackMode of
state_functions ->
@@ -822,11 +881,11 @@ loop_events(
end of
Result ->
loop_event_result(
- Parent, Debug, S, Events, Event, Result)
+ Parent, Debug, S, Events, State, Data, P, Event, Result)
catch
Result ->
loop_event_result(
- Parent, Debug, S, Events, Event, Result);
+ Parent, Debug, S, Events, State, Data, P, Event, Result);
error:badarg when CallbackMode =:= state_functions ->
case erlang:get_stacktrace() of
[{erlang,apply,[Module,State,_],_}|Stacktrace] ->
@@ -835,9 +894,11 @@ loop_events(
error,
{undef_state_function,{Module,State,Args}},
Stacktrace,
- Debug, S, Q);
+ Debug, S, [Event|Events], State, Data, P);
Stacktrace ->
- terminate(error, badarg, Stacktrace, Debug, S, Q)
+ terminate(
+ error, badarg, Stacktrace,
+ Debug, S, [Event|Events], State, Data, P)
end;
error:undef ->
%% Process an undef to check for the simple mistake
@@ -852,7 +913,7 @@ loop_events(
error,
{undef_state_function,{Module,State,Args}},
Stacktrace,
- Debug, S, Q);
+ Debug, S, [Event|Events], State, Data, P);
[{Module,handle_event,
[Type,Content,State,Data]=Args,
_}
@@ -860,86 +921,85 @@ loop_events(
when CallbackMode =:= handle_event_function ->
terminate(
error,
- {undef_state_function,
- {Module,handle_event,Args}},
+ {undef_state_function,{Module,handle_event,Args}},
Stacktrace,
- Debug, S, Q);
+ Debug, S, [Event|Events], State, Data, P);
Stacktrace ->
- terminate(error, undef, Stacktrace, Debug, S, Q)
+ terminate(
+ error, undef, Stacktrace,
+ Debug, S, [Event|Events], State, Data, P)
end;
Class:Reason ->
Stacktrace = erlang:get_stacktrace(),
- terminate(Class, Reason, Stacktrace, Debug, S, Q)
+ terminate(
+ Class, Reason, Stacktrace,
+ Debug, S, [Event|Events], State, Data, P)
end.
%% Interpret all callback return variants
loop_event_result(
- Parent, Debug,
- #{state := State, data := Data} = S,
- Events, Event, Result) ->
- %% From now until we loop back to the loop_events/4
- %% the state and data fields in S are old
+ Parent, Debug, S, Events, State, Data, P, Event, Result) ->
case Result of
stop ->
- ?TERMINATE(exit, normal, Debug, S, [Event|Events]);
+ terminate(
+ exit, normal, ?STACKTRACE(),
+ Debug, S, [Event|Events], State, Data, P);
{stop,Reason} ->
- ?TERMINATE(exit, Reason, Debug, S, [Event|Events]);
+ terminate(
+ exit, Reason, ?STACKTRACE(),
+ Debug, S, [Event|Events], State, Data, P);
{stop,Reason,NewData} ->
- NewS = S#{data := NewData},
- Q = [Event|Events],
- ?TERMINATE(exit, Reason, Debug, NewS, Q);
+ terminate(
+ exit, Reason, ?STACKTRACE(),
+ Debug, S, [Event|Events], State, NewData, P);
{stop_and_reply,Reason,Replies} ->
Q = [Event|Events],
- [Class,NewReason,Stacktrace,NewDebug] =
- reply_then_terminate(
- exit, Reason, ?STACKTRACE(), Debug, S, Q, Replies),
- %% Since we got back here Replies was bad
- terminate(Class, NewReason, Stacktrace, NewDebug, S, Q);
+ reply_then_terminate(
+ exit, Reason, ?STACKTRACE(),
+ Debug, S, Q, State, Data, P, Replies);
{stop_and_reply,Reason,Replies,NewData} ->
- NewS = S#{data := NewData},
Q = [Event|Events],
- [Class,NewReason,Stacktrace,NewDebug] =
- reply_then_terminate(
- exit, Reason, ?STACKTRACE(), Debug, NewS, Q, Replies),
- %% Since we got back here Replies was bad
- terminate(Class, NewReason, Stacktrace, NewDebug, NewS, Q);
+ reply_then_terminate(
+ exit, Reason, ?STACKTRACE(),
+ Debug, S, Q, State, NewData, P, Replies);
{next_state,NextState,NewData} ->
loop_event_actions(
- Parent, Debug, S, Events, Event,
- State, NextState, NewData, []);
+ Parent, Debug, S, Events,
+ State, NewData, P, Event, NextState, []);
{next_state,NextState,NewData,Actions} ->
loop_event_actions(
- Parent, Debug, S, Events, Event,
- State, NextState, NewData, Actions);
+ Parent, Debug, S, Events,
+ State, NewData, P, Event, NextState, Actions);
{keep_state,NewData} ->
loop_event_actions(
- Parent, Debug, S, Events, Event,
- State, State, NewData, []);
+ Parent, Debug, S, Events,
+ State, NewData, P, Event, State, []);
{keep_state,NewData,Actions} ->
loop_event_actions(
- Parent, Debug, S, Events, Event,
- State, State, NewData, Actions);
+ Parent, Debug, S, Events,
+ State, NewData, P, Event, State, Actions);
keep_state_and_data ->
loop_event_actions(
- Parent, Debug, S, Events, Event,
- State, State, Data, []);
+ Parent, Debug, S, Events,
+ State, Data, P, Event, State, []);
{keep_state_and_data,Actions} ->
loop_event_actions(
- Parent, Debug, S, Events, Event,
- State, State, Data, Actions);
+ Parent, Debug, S, Events,
+ State, Data, P, Event, State, Actions);
_ ->
- ?TERMINATE(
- error, {bad_return_value,Result}, Debug, S, [Event|Events])
+ terminate(
+ error, {bad_return_value,Result}, ?STACKTRACE(),
+ Debug, S, [Event|Events], State, Data, P)
end.
loop_event_actions(
- Parent, Debug, S, Events, Event, State, NextState, NewData, Actions) ->
- Postpone = false, % Shall we postpone this event, true or false
+ Parent, Debug, S, Events, State, NewData, P, Event, NextState, Actions) ->
+ Postpone = false, % Shall we postpone this event; boolean()
Hibernate = false,
Timeout = undefined,
NextEvents = [],
loop_event_actions(
- Parent, Debug, S, Events, Event, State, NextState, NewData,
+ Parent, Debug, S, Events, State, NewData, P, Event, NextState,
if
is_list(Actions) ->
Actions;
@@ -948,97 +1008,103 @@ loop_event_actions(
end,
Postpone, Hibernate, Timeout, NextEvents).
%%
-%% Process all action()s
+%% Process all actions
loop_event_actions(
- Parent, Debug, S, Events, Event,
- State, NextState, NewData, [Action|Actions],
+ Parent, Debug, S, Events,
+ State, NewData, P, Event, NextState, [Action|Actions],
Postpone, Hibernate, Timeout, NextEvents) ->
case Action of
%% Actual actions
{reply,From,Reply} ->
case from(From) of
true ->
- NewDebug = do_reply(Debug, S, From, Reply),
+ NewDebug = do_reply(Debug, S, State, From, Reply),
loop_event_actions(
- Parent, NewDebug, S, Events, Event,
- State, NextState, NewData, Actions,
+ Parent, NewDebug, S, Events,
+ State, NewData, P, Event, NextState, Actions,
Postpone, Hibernate, Timeout, NextEvents);
false ->
- ?TERMINATE(
- error, {bad_action,Action}, Debug, S, [Event|Events])
+ terminate(
+ error, {bad_action,Action}, ?STACKTRACE(),
+ Debug, S, [Event|Events], State, NewData, P)
end;
{next_event,Type,Content} ->
case event_type(Type) of
true ->
loop_event_actions(
- Parent, Debug, S, Events, Event,
- State, NextState, NewData, Actions,
+ Parent, Debug, S, Events,
+ State, NewData, P, Event, NextState, Actions,
Postpone, Hibernate, Timeout,
[{Type,Content}|NextEvents]);
false ->
- ?TERMINATE(
- error, {bad_action,Action}, Debug, S, [Event|Events])
+ terminate(
+ error, {bad_action,Action}, ?STACKTRACE(),
+ Debug, S, [Event|Events], State, NewData, P)
end;
%% Actions that set options
{postpone,NewPostpone} when is_boolean(NewPostpone) ->
loop_event_actions(
- Parent, Debug, S, Events, Event,
- State, NextState, NewData, Actions,
+ Parent, Debug, S, Events,
+ State, NewData, P, Event, NextState, Actions,
NewPostpone, Hibernate, Timeout, NextEvents);
{postpone,_} ->
- ?TERMINATE(
- error, {bad_action,Action}, Debug, S, [Event|Events]);
+ terminate(
+ error, {bad_action,Action}, ?STACKTRACE(),
+ Debug, S, [Event|Events], State, NewData, P);
postpone ->
loop_event_actions(
- Parent, Debug, S, Events, Event,
- State, NextState, NewData, Actions,
+ Parent, Debug, S, Events,
+ State, NewData, P, Event, NextState, Actions,
true, Hibernate, Timeout, NextEvents);
{hibernate,NewHibernate} when is_boolean(NewHibernate) ->
loop_event_actions(
- Parent, Debug, S, Events, Event,
- State, NextState, NewData, Actions,
+ Parent, Debug, S, Events,
+ State, NewData, P, Event, NextState, Actions,
Postpone, NewHibernate, Timeout, NextEvents);
{hibernate,_} ->
- ?TERMINATE(
- error, {bad_action,Action}, Debug, S, [Event|Events]);
+ terminate(
+ error, {bad_action,Action}, ?STACKTRACE(),
+ Debug, S, [Event|Events], State, NewData, P);
hibernate ->
loop_event_actions(
- Parent, Debug, S, Events, Event,
- State, NextState, NewData, Actions,
+ Parent, Debug, S, Events,
+ State, NewData, P, Event, NextState, Actions,
Postpone, true, Timeout, NextEvents);
{timeout,infinity,_} -> % Clear timer - it will never trigger
loop_event_actions(
- Parent, Debug, S, Events, Event,
- State, NextState, NewData, Actions,
+ Parent, Debug, S, Events,
+ State, NewData, P, Event, NextState, Actions,
Postpone, Hibernate, undefined, NextEvents);
{timeout,Time,_} = NewTimeout when is_integer(Time), Time >= 0 ->
loop_event_actions(
- Parent, Debug, S, Events, Event,
- State, NextState, NewData, Actions,
+ Parent, Debug, S, Events,
+ State, NewData, P, Event, NextState, Actions,
Postpone, Hibernate, NewTimeout, NextEvents);
{timeout,_,_} ->
- ?TERMINATE(
- error, {bad_action,Action}, Debug, S, [Event|Events]);
+ terminate(
+ error, {bad_action,Action}, ?STACKTRACE(),
+ Debug, S, [Event|Events], State, NewData, P);
infinity -> % Clear timer - it will never trigger
loop_event_actions(
- Parent, Debug, S, Events, Event,
- State, NextState, NewData, Actions,
+ Parent, Debug, S, Events,
+ State, NewData, P, Event, NextState, Actions,
Postpone, Hibernate, undefined, NextEvents);
Time when is_integer(Time), Time >= 0 ->
NewTimeout = {timeout,Time,Time},
loop_event_actions(
- Parent, Debug, S, Events, Event,
- State, NextState, NewData, Actions,
+ Parent, Debug, S, Events,
+ State, NewData, P, Event, NextState, Actions,
Postpone, Hibernate, NewTimeout, NextEvents);
_ ->
- ?TERMINATE(
- error, {bad_action,Action}, Debug, S, [Event|Events])
+ terminate(
+ error, {bad_action,Action}, ?STACKTRACE(),
+ Debug, S, [Event|Events], State, NewData, P)
end;
%%
%% End of actions list
loop_event_actions(
- Parent, Debug, #{postponed := P0} = S, Events, Event,
- State, NextState, NewData, [],
+ Parent, Debug, S, Events,
+ State, NewData, P0, Event, NextState, [],
Postpone, Hibernate, Timeout, NextEvents) ->
%%
%% All options have been collected and next_events are buffered.
@@ -1059,89 +1125,62 @@ loop_event_actions(
{lists:reverse(P1, Events),[]}
end,
%% Place next events first in queue
- Q3 = lists:reverse(NextEvents, Q2),
+ Q = lists:reverse(NextEvents, Q2),
%%
NewDebug =
sys_debug(
- Debug, S,
+ Debug, S, State,
case Postpone of
true ->
{postpone,Event,NextState};
false ->
{consume,Event,NextState}
end),
- %% Have a peek on the event queue so we can avoid starting
- %% the state timer unless we have to
- {Q,Timer} =
- case Timeout of
- undefined ->
- %% No state timeout has been requested
- {Q3,undefined};
- {timeout,Time,EventContent} ->
- %% A state timeout has been requested
- case Q3 of
- [] when Time =:= 0 ->
- %% Immediate timeout - simulate it
- %% so we do not get the timeout message
- %% after any received event
- {[{timeout,EventContent}],undefined};
- [] ->
- %% Actually start a timer
- {Q3,erlang:start_timer(Time, self(), EventContent)};
- _ ->
- %% Do not start a timer since any queued
- %% event cancels the state timer so we pretend
- %% that the timer has been started and cancelled
- {Q3,undefined}
- end
- end,
- %% Loop to top of event queue loop; process next event
loop_events(
- Parent, NewDebug,
- S#{
- state := NextState,
- data := NewData,
- timer := Timer,
- postponed := P,
- hibernate := Hibernate},
- Q, Hibernate).
+ Parent, NewDebug, S, Q, NextState, NewData, P, Hibernate, Timeout).
%%---------------------------------------------------------------------------
%% Server helpers
-reply_then_terminate(Class, Reason, Stacktrace, Debug, S, Q, Replies) ->
+reply_then_terminate(
+ Class, Reason, Stacktrace,
+ Debug, S, Q, State, Data, P, Replies) ->
if
is_list(Replies) ->
do_reply_then_terminate(
- Class, Reason, Stacktrace, Debug, S, Q, Replies);
+ Class, Reason, Stacktrace,
+ Debug, S, Q, State, Data, P, Replies);
true ->
do_reply_then_terminate(
- Class, Reason, Stacktrace, Debug, S, Q, [Replies])
+ Class, Reason, Stacktrace,
+ Debug, S, Q, State, Data, P, [Replies])
end.
%%
-do_reply_then_terminate(Class, Reason, Stacktrace, Debug, S, Q, []) ->
- terminate(Class, Reason, Stacktrace, Debug, S, Q);
do_reply_then_terminate(
- Class, Reason, Stacktrace, Debug, S, Q, [R|Rs]) ->
+ Class, Reason, Stacktrace, Debug, S, Q, State, Data, P, []) ->
+ terminate(Class, Reason, Stacktrace, Debug, S, Q, State, Data, P);
+do_reply_then_terminate(
+ Class, Reason, Stacktrace, Debug, S, Q, State, Data, P, [R|Rs]) ->
case R of
{reply,{_To,_Tag}=From,Reply} ->
- NewDebug = do_reply(Debug, S, From, Reply),
+ NewDebug = do_reply(Debug, S, State, From, Reply),
do_reply_then_terminate(
- Class, Reason, Stacktrace, NewDebug, S, Q, Rs);
+ Class, Reason, Stacktrace,
+ NewDebug, S, Q, State, Data, P, Rs);
_ ->
- [error,{bad_action,R},?STACKTRACE(),Debug]
+ terminate(
+ error, {bad_action,R}, ?STACKTRACE(),
+ Debug, S, Q, State, Data, P)
end.
-do_reply(Debug, S, From, Reply) ->
+do_reply(Debug, S, State, From, Reply) ->
reply(From, Reply),
- sys_debug(Debug, S, {out,Reply,From}).
+ sys_debug(Debug, S, State, {out,Reply,From}).
terminate(
- Class, Reason, Stacktrace, Debug,
- #{module := Module,
- state := State, data := Data} = S,
- Q) ->
+ Class, Reason, Stacktrace,
+ Debug, #{module := Module} = S, Q, State, Data, P) ->
try Module:terminate(Reason, State, Data) of
_ -> ok
catch
@@ -1149,8 +1188,8 @@ terminate(
C:R ->
ST = erlang:get_stacktrace(),
error_info(
- C, R, ST, Debug, S, Q,
- format_status(terminate, get(), S)),
+ C, R, ST, Debug, S, Q, P,
+ format_status(terminate, get(), S, State, Data)),
erlang:raise(C, R, ST)
end,
case Reason of
@@ -1159,8 +1198,8 @@ terminate(
{shutdown,_} -> ok;
_ ->
error_info(
- Class, Reason, Stacktrace, Debug, S, Q,
- format_status(terminate, get(), S))
+ Class, Reason, Stacktrace, Debug, S, Q, P,
+ format_status(terminate, get(), S, State, Data))
end,
case Stacktrace of
[] ->
@@ -1171,9 +1210,8 @@ terminate(
error_info(
Class, Reason, Stacktrace, Debug,
- #{name := Name, callback_mode := CallbackMode,
- state := State, postponed := P},
- Q, FmtData) ->
+ #{name := Name, callback_mode := CallbackMode},
+ Q, P, FmtData) ->
{FixedReason,FixedStacktrace} =
case Stacktrace of
[{M,F,Args,_}|ST]
@@ -1202,46 +1240,49 @@ error_info(
error_logger:format(
"** State machine ~p terminating~n" ++
case Q of
- [] ->
- "";
- _ ->
- "** Last event = ~p~n"
+ [] -> "";
+ _ -> "** Last event = ~p~n"
end ++
- "** When Server state = ~p~n" ++
+ "** When server state = ~p~n" ++
"** Reason for termination = ~w:~p~n" ++
- "** State = ~p~n" ++
"** Callback mode = ~p~n" ++
- "** Queued/Postponed = ~w/~w~n" ++
+ case Q of
+ [_,_|_] -> "** Queued = ~p~n";
+ _ -> ""
+ end ++
+ case P of
+ [] -> "";
+ _ -> "** Postponed = ~p~n"
+ end ++
case FixedStacktrace of
- [] ->
- "";
- _ ->
- "** Stacktrace =~n"
- "** ~p~n"
+ [] -> "";
+ _ -> "** Stacktrace =~n** ~p~n"
end,
[Name |
case Q of
- [] ->
- [];
- [Event|_] ->
- [Event]
+ [] -> [];
+ [Event|_] -> [Event]
end] ++
[FmtData,Class,FixedReason,
- State,CallbackMode,length(Q),length(P)] ++
+ CallbackMode] ++
+ case Q of
+ [_|[_|_] = Events] -> [Events];
+ _ -> []
+ end ++
+ case P of
+ [] -> [];
+ _ -> [P]
+ end ++
case FixedStacktrace of
- [] ->
- [];
- _ ->
- [FixedStacktrace]
+ [] -> [];
+ _ -> [FixedStacktrace]
end),
sys:print_log(Debug),
ok.
%% Call Module:format_status/2 or return a default value
-format_status(
- Opt, PDict,
- #{module := Module, state := State, data := Data}) ->
+format_status(Opt, PDict, #{module := Module}, State, Data) ->
case erlang:function_exported(Module, format_status, 2) of
true ->
try Module:format_status(Opt, [PDict,State,Data])
diff --git a/lib/stdlib/src/otp_internal.erl b/lib/stdlib/src/otp_internal.erl
index 7a59523f06..c3ad261daa 100644
--- a/lib/stdlib/src/otp_internal.erl
+++ b/lib/stdlib/src/otp_internal.erl
@@ -35,7 +35,7 @@
obsolete(Module, Name, Arity) ->
case obsolete_1(Module, Name, Arity) of
{deprecated=Tag,{_,_,_}=Replacement} ->
- {Tag,Replacement,"in a future release"};
+ {Tag,Replacement,"a future release"};
{_,String}=Ret when is_list(String) ->
Ret;
{_,_,_}=Ret ->
diff --git a/lib/stdlib/src/proc_lib.erl b/lib/stdlib/src/proc_lib.erl
index fdc2ae4070..3dc1848550 100644
--- a/lib/stdlib/src/proc_lib.erl
+++ b/lib/stdlib/src/proc_lib.erl
@@ -43,9 +43,14 @@
%%-----------------------------------------------------------------------------
-type priority_level() :: 'high' | 'low' | 'max' | 'normal'.
+-type max_heap_size() :: non_neg_integer() |
+ #{ size => non_neg_integer(),
+ kill => true,
+ error_logger => true}.
-type spawn_option() :: 'link'
| 'monitor'
| {'priority', priority_level()}
+ | {'max_heap_size', max_heap_size()}
| {'min_heap_size', non_neg_integer()}
| {'min_bin_vheap_size', non_neg_integer()}
| {'fullsweep_after', non_neg_integer()}
@@ -474,18 +479,12 @@ trans_init(gen,init_it,[gen_server,_,_,supervisor_bridge,[Module|_],_]) ->
{supervisor_bridge,Module,1};
trans_init(gen,init_it,[gen_server,_,_,_,supervisor_bridge,[Module|_],_]) ->
{supervisor_bridge,Module,1};
-trans_init(gen,init_it,[GenMod,_,_,Module,_,_])
- when GenMod =:= gen_server;
- GenMod =:= gen_statem;
- GenMod =:= gen_fsm ->
- {Module,init,1};
-trans_init(gen,init_it,[GenMod,_,_,_,Module|_])
- when GenMod =:= gen_server;
- GenMod =:= gen_statem;
- GenMod =:= gen_fsm ->
- {Module,init,1};
trans_init(gen,init_it,[gen_event|_]) ->
{gen_event,init_it,6};
+trans_init(gen,init_it,[_GenMod,_,_,Module,_,_]) when is_atom(Module) ->
+ {Module,init,1};
+trans_init(gen,init_it,[_GenMod,_,_,_,Module|_]) when is_atom(Module) ->
+ {Module,init,1};
trans_init(M, F, A) when is_atom(M), is_atom(F) ->
{M,F,length(A)}.
diff --git a/lib/stdlib/src/stdlib.app.src b/lib/stdlib/src/stdlib.app.src
index 32bcdc4f2a..09176d2ca0 100644
--- a/lib/stdlib/src/stdlib.app.src
+++ b/lib/stdlib/src/stdlib.app.src
@@ -106,7 +106,7 @@
dets]},
{applications, [kernel]},
{env, []},
- {runtime_dependencies, ["sasl-2.6","kernel-4.1","erts-7.3","crypto-3.3",
+ {runtime_dependencies, ["sasl-3.0","kernel-5.0","erts-8.0","crypto-3.3",
"compiler-5.0"]}
]}.
diff --git a/lib/stdlib/src/supervisor.erl b/lib/stdlib/src/supervisor.erl
index 38b764541a..a594c66fa7 100644
--- a/lib/stdlib/src/supervisor.erl
+++ b/lib/stdlib/src/supervisor.erl
@@ -246,7 +246,7 @@ check_childspecs(ChildSpecs) when is_list(ChildSpecs) ->
check_childspecs(X) -> {error, {badarg, X}}.
%%%-----------------------------------------------------------------
-%%% Called by timer:apply_after from restart/2
+%%% Called by restart/2
-spec try_again_restart(SupRef, Child) -> ok when
SupRef :: sup_ref(),
Child :: child_id() | pid().
@@ -571,8 +571,8 @@ count_child(#child{pid = Pid, child_type = supervisor},
end.
-%%% If a restart attempt failed, this message is sent via
-%%% timer:apply_after(0,...) in order to give gen_server the chance to
+%%% If a restart attempt failed, this message is cast
+%%% from restart/2 in order to give gen_server the chance to
%%% check it's inbox before trying again.
-spec handle_cast({try_again_restart, child_id() | pid()}, state()) ->
{'noreply', state()} | {stop, shutdown, state()}.
@@ -790,16 +790,10 @@ restart(Child, State) ->
Id = if ?is_simple(State) -> Child#child.pid;
true -> Child#child.name
end,
- {ok, _TRef} = timer:apply_after(0,
- ?MODULE,
- try_again_restart,
- [self(),Id]),
+ ok = try_again_restart(self(), Id),
{ok,NState2};
{try_again, NState2, #child{name=ChName}} ->
- {ok, _TRef} = timer:apply_after(0,
- ?MODULE,
- try_again_restart,
- [self(),ChName]),
+ ok = try_again_restart(self(), ChName),
{ok,NState2};
Other ->
Other
diff --git a/lib/stdlib/test/binary_module_SUITE.erl b/lib/stdlib/test/binary_module_SUITE.erl
index 55fdcdd054..c5cfea5e9e 100644
--- a/lib/stdlib/test/binary_module_SUITE.erl
+++ b/lib/stdlib/test/binary_module_SUITE.erl
@@ -19,9 +19,7 @@
%%
-module(binary_module_SUITE).
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_testcase/2, end_per_testcase/2,
- init_per_group/2,end_per_group/2,
+-export([all/0, suite/0,
interesting/1,scope_return/1,random_ref_comp/1,random_ref_sr_comp/1,
random_ref_fla_comp/1,parts/1, bin_to_list/1, list_to_bin/1,
copy/1, referenced/1,guard/1,encode_decode/1,badargs/1,longest_common_trap/1]).
@@ -30,15 +28,9 @@
-include_lib("common_test/include/ct.hrl").
-init_per_testcase(_Case, Config) ->
- Config.
-
-end_per_testcase(_Case, _Config) ->
- ok.
-
suite() ->
[{ct_hooks,[ts_install_cth]},
- {timetrap,{minutes,30}}].
+ {timetrap,{minutes,10}}].
all() ->
[scope_return,interesting, random_ref_fla_comp, random_ref_sr_comp,
@@ -46,21 +38,6 @@ all() ->
referenced, guard, encode_decode, badargs,
longest_common_trap].
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-define(MASK_ERROR(EXPR),mask_error((catch (EXPR)))).
@@ -961,6 +938,7 @@ random_parts(X,N) ->
%% Test pseudorandomly generated cases against reference implementation.
random_ref_comp(Config) when is_list(Config) ->
+ ct:timetrap({minutes,30}), %% valgrind needs a lot of time
put(success_counter,0),
rand:seed(exsplus, {1271,769940,559934}),
Nr = {1,40},
@@ -991,6 +969,7 @@ random_ref_comp(Config) when is_list(Config) ->
%% Test pseudorandomly generated cases against reference implementation
%% of split and replace.
random_ref_sr_comp(Config) when is_list(Config) ->
+ ct:timetrap({minutes,30}), %% valgrind needs a lot
put(success_counter,0),
rand:seed(exsplus, {1271,769940,559934}),
Nr = {1,40},
diff --git a/lib/stdlib/test/epp_SUITE.erl b/lib/stdlib/test/epp_SUITE.erl
index ef2c912c57..4078513e38 100644
--- a/lib/stdlib/test/epp_SUITE.erl
+++ b/lib/stdlib/test/epp_SUITE.erl
@@ -27,7 +27,8 @@
pmod/1, not_circular/1, skip_header/1, otp_6277/1, otp_7702/1,
otp_8130/1, overload_mac/1, otp_8388/1, otp_8470/1,
otp_8562/1, otp_8665/1, otp_8911/1, otp_10302/1, otp_10820/1,
- otp_11728/1, encoding/1, extends/1, function_macro/1]).
+ otp_11728/1, encoding/1, extends/1, function_macro/1,
+ test_error/1, test_warning/1]).
-export([epp_parse_erl_form/2]).
@@ -67,7 +68,7 @@ all() ->
not_circular, skip_header, otp_6277, otp_7702, otp_8130,
overload_mac, otp_8388, otp_8470, otp_8562,
otp_8665, otp_8911, otp_10302, otp_10820, otp_11728,
- encoding, extends, function_macro].
+ encoding, extends, function_macro, test_error, test_warning].
groups() ->
[{upcase_mac, [], [upcase_mac_1, upcase_mac_2]},
@@ -1055,7 +1056,65 @@ ifdef(Config) ->
],
[] = run(Config, Ts).
+%% OTP-12847: Test the -error directive.
+test_error(Config) ->
+ Cs = [{error_c1,
+ <<"-error(\"string and macro: \" ?MODULE_STRING).\n"
+ "-ifdef(NOT_DEFINED).\n"
+ " -error(\"this one will be skipped\").\n"
+ "-endif.\n">>,
+ {errors,[{1,epp,{error,"string and macro: epp_test"}}],[]}},
+
+ {error_c2,
+ <<"-ifdef(CONFIG_A).\n"
+ " t() -> a.\n"
+ "-else.\n"
+ "-ifdef(CONFIG_B).\n"
+ " t() -> b.\n"
+ "-else.\n"
+ "-error(\"Neither CONFIG_A nor CONFIG_B are available\").\n"
+ "-endif.\n"
+ "-endif.\n">>,
+ {errors,[{7,epp,{error,"Neither CONFIG_A nor CONFIG_B are available"}}],[]}},
+
+ {error_c3,
+ <<"-error(a b c).\n">>,
+ {errors,[{1,epp,{bad,error}}],[]}}
+ ],
+
+ [] = compile(Config, Cs),
+ ok.
+
+%% OTP-12847: Test the -warning directive.
+test_warning(Config) ->
+ Cs = [{warn_c1,
+ <<"-warning({a,term,?MODULE}).\n"
+ "-ifdef(NOT_DEFINED).\n"
+ "-warning(\"this one will be skipped\").\n"
+ "-endif.\n">>,
+ {warnings,[{1,epp,{warning,{a,term,epp_test}}}]}},
+
+ {warn_c2,
+ <<"-ifdef(CONFIG_A).\n"
+ " t() -> a.\n"
+ "-else.\n"
+ "-ifdef(CONFIG_B).\n"
+ " t() -> b.\n"
+ "-else.\n"
+ " t() -> c.\n"
+ "-warning(\"Using fallback\").\n"
+ "-endif.\n"
+ "-endif.\n">>,
+ {warnings,[{8,epp,{warning,"Using fallback"}}]}},
+
+ {warn_c3,
+ <<"-warning(a b c).\n">>,
+ {errors,[{1,epp,{bad,warning}}],[]}}
+ ],
+
+ [] = compile(Config, Cs),
+ ok.
%% Advanced test on overloading macros.
overload_mac(Config) when is_list(Config) ->
diff --git a/lib/stdlib/test/erl_lint_SUITE.erl b/lib/stdlib/test/erl_lint_SUITE.erl
index b0214e5238..d916eb3eef 100644
--- a/lib/stdlib/test/erl_lint_SUITE.erl
+++ b/lib/stdlib/test/erl_lint_SUITE.erl
@@ -2003,7 +2003,7 @@ otp_5362(Config) when is_list(Config) ->
{error,
[{5,erl_lint,{call_to_redefined_old_bif,{spawn,1}}}],
[{4,erl_lint,{deprecated,{erlang,hash,2},{erlang,phash2,2},
- "in a future release"}}]}},
+ "a future release"}}]}},
{otp_5362_5,
<<"-compile(nowarn_deprecated_function).
@@ -2063,7 +2063,7 @@ otp_5362(Config) when is_list(Config) ->
{nowarn_bif_clash,{spawn,1}}]}, % has no effect
{warnings,
[{5,erl_lint,{deprecated,{erlang,hash,2},{erlang,phash2,2},
- "in a future release"}}]}},
+ "a future release"}}]}},
{otp_5362_9,
<<"-include_lib(\"stdlib/include/qlc.hrl\").
@@ -2093,7 +2093,7 @@ otp_5362(Config) when is_list(Config) ->
[],
{warnings,
[{1,erl_lint,{deprecated,{erlang,hash,2},
- {erlang,phash2,2},"in a future release"}}]}},
+ {erlang,phash2,2},"a future release"}}]}},
{call_removed_function,
<<"t(X) -> regexp:match(X).">>,
diff --git a/lib/stdlib/test/ets_SUITE.erl b/lib/stdlib/test/ets_SUITE.erl
index 15e3142408..8c1c625676 100644
--- a/lib/stdlib/test/ets_SUITE.erl
+++ b/lib/stdlib/test/ets_SUITE.erl
@@ -125,7 +125,7 @@ end_per_testcase(_Func, _Config) ->
suite() ->
[{ct_hooks,[ts_install_cth]},
- {timetrap,{minutes,20}}].
+ {timetrap,{minutes,5}}].
all() ->
[{group, new}, {group, insert}, {group, lookup},
@@ -698,7 +698,7 @@ chk_normal_tab_struct_size() ->
io:format("?TAB_STRUCT_SZ=~p~n", [?TAB_STRUCT_SZ]),
ok.
-adjust_xmem([T1,T2,T3,T4], {A0,B0,C0,D0} = _Mem0) ->
+adjust_xmem([_T1,_T2,_T3,_T4], {A0,B0,C0,D0} = _Mem0) ->
%% Adjust for 64-bit, smp, and os:
%% Table struct size may differ.
@@ -2809,16 +2809,22 @@ privacy_do(Opts) ->
privacy_check(pub,prot,priv),
Owner ! {shift,1,{pub,prot,priv}},
- receive {Pub1,Prot1,Priv1} -> ok end,
- privacy_check(Pub1,Prot1,Priv1),
+ receive
+ {Pub1,Prot1,Priv1} ->
+ ok = privacy_check(Pub1,Prot1,Priv1),
+ Owner ! {shift,2,{Pub1,Prot1,Priv1}}
+ end,
- Owner ! {shift,2,{Pub1,Prot1,Priv1}},
- receive {Pub2,Prot2,Priv2} -> ok end,
- privacy_check(Pub2,Prot2,Priv2),
+ receive
+ {Pub2,Prot2,Priv2} ->
+ ok = privacy_check(Pub2,Prot2,Priv2),
+ Owner ! {shift,0,{Pub2,Prot2,Priv2}}
+ end,
- Owner ! {shift,0,{Pub2,Prot2,Priv2}},
- receive {Pub2,Prot2,Priv2} -> ok end,
- privacy_check(Pub2,Prot2,Priv2),
+ receive
+ {Pub3,Prot3,Priv3} ->
+ ok = privacy_check(Pub3,Prot3,Priv3)
+ end,
Owner ! die,
receive {'EXIT',Owner,_} -> ok end,
@@ -2836,7 +2842,8 @@ privacy_check(Pub,Prot,Priv) ->
{'EXIT',{badarg,_}} = (catch ets:insert(Priv,{3,foo})),
%% check that it really wasn't written, either
- [] = ets:lookup(Prot,foo).
+ [] = ets:lookup(Prot,foo),
+ ok.
privacy_owner(Boss, Opts) ->
ets_new(pub, [public,named_table | Opts]),
@@ -3197,7 +3204,6 @@ delete_large_named_table_1(Name, Flags, Data, Fix) ->
true = ets:safe_fixtable(Tab, true),
lists:foreach(fun({K,_}) -> ets:delete(Tab, K) end, Data)
end,
- Parent = self(),
{Pid, MRef} = my_spawn_opt(fun() ->
receive
ets_new ->
@@ -3297,6 +3303,7 @@ exit_large_table_owner_do(Opts,{FEData,Config}) ->
verify_rescheduling_exit(Config, FEData, Opts, false, 1, 1).
exit_many_large_table_owner(Config) when is_list(Config) ->
+ ct:timetrap({minutes,30}), %% valgrind needs a lot
%%Data = [{erlang:phash2(I, 16#ffffff),I} || I <- lists:seq(1, 500000)],
FEData = fun(Do) -> repeat_while(fun(500000) -> {false,ok};
(I) -> Do({erlang:phash2(I, 16#ffffff),I}),
@@ -4270,6 +4277,7 @@ do_lookup_element(Tab, N, M) ->
heavy_concurrent(Config) when is_list(Config) ->
+ ct:timetrap({minutes,30}), %% valgrind needs a lot of time
repeat_for_opts(do_heavy_concurrent).
do_heavy_concurrent(Opts) ->
diff --git a/lib/stdlib/test/gen_statem_SUITE.erl b/lib/stdlib/test/gen_statem_SUITE.erl
index 3deb5fd986..364314f91b 100644
--- a/lib/stdlib/test/gen_statem_SUITE.erl
+++ b/lib/stdlib/test/gen_statem_SUITE.erl
@@ -634,12 +634,14 @@ sys1(Config) ->
stop_it(Pid).
code_change(Config) ->
+ Mode = handle_event_function,
{ok,Pid} = gen_statem:start(?MODULE, start_arg(Config, []), []),
{idle,data} = sys:get_state(Pid),
sys:suspend(Pid),
- sys:change_code(Pid, ?MODULE, old_vsn, state_functions),
+ sys:change_code(Pid, ?MODULE, old_vsn, Mode),
sys:resume(Pid),
- {idle,{old_vsn,data,state_functions}} = sys:get_state(Pid),
+ {idle,{old_vsn,data,Mode}} = sys:get_state(Pid),
+ Mode = gen_statem:call(Pid, get_callback_mode),
stop_it(Pid).
call_format_status(Config) ->
@@ -1478,6 +1480,8 @@ next_events(Type, Content, Data) ->
end.
+handle_common_events({call,From}, get_callback_mode, _, _) ->
+ {keep_state_and_data,{reply,From,state_functions}};
handle_common_events({call,From}, get, State, Data) ->
{keep_state,Data,
[{reply,From,{state,State,Data}}]};
@@ -1501,6 +1505,8 @@ handle_common_events(cast, {'alive?',Pid}, _, Data) ->
handle_common_events(_, _, _, _) ->
undefined.
+handle_event({call,From}, get_callback_mode, _, _) ->
+ {keep_state_and_data,{reply,From,handle_event_function}};
%% Wrapper state machine that uses a map state machine spec
handle_event(
Type, Event, State, [Data|Machine])
diff --git a/lib/stdlib/test/io_SUITE.erl b/lib/stdlib/test/io_SUITE.erl
index be6b470ca7..7d48cbc97c 100644
--- a/lib/stdlib/test/io_SUITE.erl
+++ b/lib/stdlib/test/io_SUITE.erl
@@ -19,10 +19,7 @@
%%
-module(io_SUITE).
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2]).
-
--export([init_per_testcase/2, end_per_testcase/2]).
+-export([all/0, suite/0]).
-export([error_1/1, float_g/1, otp_5403/1, otp_5813/1, otp_6230/1,
otp_6282/1, otp_6354/1, otp_6495/1, otp_6517/1, otp_6502/1,
@@ -51,12 +48,6 @@
-define(privdir(Conf), proplists:get_value(priv_dir, Conf)).
-endif.
-init_per_testcase(_Case, Config) ->
- Config.
-
-end_per_testcase(_Case, _Config) ->
- ok.
-
suite() ->
[{ct_hooks,[ts_install_cth]},
{timetrap,{minutes,1}}].
@@ -72,22 +63,6 @@ all() ->
io_lib_width_too_small, io_with_huge_message_queue,
format_string, maps, coverage].
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
%% Error cases for output.
error_1(Config) when is_list(Config) ->
%% We don't do erroneous output on stdout - the test server
@@ -952,7 +927,7 @@ otp_6708(Config) when is_list(Config) ->
otp_7084() ->
- [{timetrap,{minutes,3}}].
+ [{timetrap,{minutes,6}}]. %% valgrind needs a lot of time
%% OTP-7084. Printing floating point numbers nicely.
otp_7084(Config) when is_list(Config) ->
@@ -1830,13 +1805,14 @@ bad_printable_range(Config) when is_list(Config) ->
Cmd = lists:concat([lib:progname()," +pcunnnnnicode -run erlang halt"]),
P = open_port({spawn, Cmd}, [stderr_to_stdout, {line, 200}]),
ok = receive
- {P, {data, {eol , "bad range of printable characters" ++ _}}} ->
- ok;
- Other ->
- Other
- after 1000 ->
- timeout
- end,
+ {P, {data, {eol , "bad range of printable characters" ++ _}}} ->
+ ok;
+ Other ->
+ Other
+ %% valgrind needs a lot of time
+ after 6000 ->
+ timeout
+ end,
catch port_close(P),
flush_from_port(P),
ok.
diff --git a/lib/stdlib/test/io_proto_SUITE.erl b/lib/stdlib/test/io_proto_SUITE.erl
index 4e39f011f6..1e286a9306 100644
--- a/lib/stdlib/test/io_proto_SUITE.erl
+++ b/lib/stdlib/test/io_proto_SUITE.erl
@@ -75,7 +75,7 @@ end_per_testcase(_Case, Config) ->
suite() ->
[{ct_hooks,[ts_install_cth]},
- {timetrap,{minutes,20}}].
+ {timetrap,{minutes,5}}].
all() ->
[setopts_getopts, unicode_options, unicode_options_gen,
@@ -462,6 +462,7 @@ unicode_options(Config) when is_list(Config) ->
%% Tests various unicode options on random generated files.
unicode_options_gen(Config) when is_list(Config) ->
+ ct:timetrap({minutes,30}), %% valgrind needs a alot of time
random:seed(1240, 900586, 553728),
PrivDir = proplists:get_value(priv_dir, Config),
AllModes = [utf8,utf16,{utf16,big},{utf16,little},
diff --git a/lib/stdlib/test/rand_SUITE.erl b/lib/stdlib/test/rand_SUITE.erl
index 1bcdc3ccd0..cb778c96d4 100644
--- a/lib/stdlib/test/rand_SUITE.erl
+++ b/lib/stdlib/test/rand_SUITE.erl
@@ -18,18 +18,13 @@
%% %CopyrightEnd%
-module(rand_SUITE).
--export([all/0, suite/0,groups/0,
- init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
- init_per_testcase/2, end_per_testcase/2
- ]).
+-export([all/0, suite/0,groups/0]).
-export([interval_int/1, interval_float/1, seed/1,
api_eq/1, reference/1,
basic_stats_uniform_1/1, basic_stats_uniform_2/1,
basic_stats_normal/1,
- plugin/1, measure/1
- ]).
+ plugin/1, measure/1]).
-export([test/0, gen/1]).
@@ -37,12 +32,6 @@
-define(LOOP, 1000000).
-init_per_testcase(_Case, Config) ->
- Config.
-
-end_per_testcase(_Case, _Config) ->
- ok.
-
suite() ->
[{ct_hooks,[ts_install_cth]},
{timetrap,{minutes,3}}].
@@ -52,19 +41,12 @@ all() ->
api_eq,
reference,
{group, basic_stats},
- plugin, measure
- ].
+ plugin, measure].
groups() ->
[{basic_stats, [parallel],
[basic_stats_uniform_1, basic_stats_uniform_2, basic_stats_normal]}].
-init_per_suite(Config) -> Config.
-end_per_suite(_Config) -> ok.
-
-init_per_group(_GroupName, Config) -> Config.
-end_per_group(_GroupName, Config) -> Config.
-
%% A simple helper to test without test_server during dev
test() ->
Tests = all(),
@@ -285,16 +267,19 @@ gen(_, _, Acc) -> lists:reverse(Acc).
%% Check that the algorithms generate sound values.
basic_stats_uniform_1(Config) when is_list(Config) ->
+ ct:timetrap({minutes,6}), %% valgrind needs a lot of time
[basic_uniform_1(?LOOP, rand:seed_s(Alg), 0.0, array:new([{default, 0}]))
|| Alg <- algs()],
ok.
basic_stats_uniform_2(Config) when is_list(Config) ->
+ ct:timetrap({minutes,6}), %% valgrind needs a lot of time
[basic_uniform_2(?LOOP, rand:seed_s(Alg), 0, array:new([{default, 0}]))
|| Alg <- algs()],
ok.
basic_stats_normal(Config) when is_list(Config) ->
+ ct:timetrap({minutes,6}), %% valgrind needs a lot of time
io:format("Testing normal~n",[]),
[basic_normal_1(?LOOP, rand:seed_s(Alg), 0, 0) || Alg <- algs()],
ok.
@@ -395,6 +380,7 @@ crypto_uniform_n(N, State0) ->
%% Not a test but measures the time characteristics of the different algorithms
measure(Suite) when is_atom(Suite) -> [];
measure(_Config) ->
+ ct:timetrap({minutes,6}), %% valgrind needs a lot of time
Algos = [crypto64|algs()],
io:format("RNG uniform integer performance~n",[]),
_ = measure_1(random, fun(State) -> {int, random:uniform_s(10000, State)} end),
diff --git a/lib/stdlib/test/select_SUITE.erl b/lib/stdlib/test/select_SUITE.erl
index e999d040c9..22b6d37e5d 100644
--- a/lib/stdlib/test/select_SUITE.erl
+++ b/lib/stdlib/test/select_SUITE.erl
@@ -59,42 +59,20 @@ config(priv_dir,_) ->
".".
-else.
%% When run in test server.
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,select_test/1,
- init_per_testcase/2, end_per_testcase/2,
- return_values/1]).
-
-init_per_testcase(_Case, Config) ->
- Config.
-
-end_per_testcase(_Case, _Config) ->
- ok.
+-export([all/0, suite/0,
+ select_test/1, return_values/1]).
suite() ->
[{ct_hooks,[ts_install_cth]},
- {timetrap,{minutes,20}}].
+ {timetrap,{minutes,1}}].
all() ->
[return_values, select_test].
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
%% Test select in numerous ways.
select_test(Config) when is_list(Config) ->
+ ct:timetrap({minutes,40}), %% valgrinds needs a lot of time
do_test(Config).
%% Test return values in specific situations for select/3 and select/1.
diff --git a/lib/stdlib/test/unicode_SUITE.erl b/lib/stdlib/test/unicode_SUITE.erl
index 81a591f433..07d63bdf22 100644
--- a/lib/stdlib/test/unicode_SUITE.erl
+++ b/lib/stdlib/test/unicode_SUITE.erl
@@ -21,10 +21,7 @@
-include_lib("common_test/include/ct.hrl").
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
- init_per_testcase/2,
- end_per_testcase/2,
+-export([all/0, suite/0,groups/0,
utf8_illegal_sequences_bif/1,
utf16_illegal_sequences_bif/1,
random_lists/1,
@@ -38,12 +35,6 @@
ex_binaries_errors_utf32_little/1,
ex_binaries_errors_utf32_big/1]).
-init_per_testcase(_Case, Config) ->
- Config.
-
-end_per_testcase(_Case, _Config) ->
- ok.
-
suite() ->
[{ct_hooks,[ts_install_cth]},
{timetrap,{minutes,20}}].
@@ -63,18 +54,6 @@ groups() ->
ex_binaries_errors_utf32_little,
ex_binaries_errors_utf32_big]}].
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
binaries_errors_limit(Config) when is_list(Config) ->
setlimit(10),
ex_binaries_errors_utf8(Config),
@@ -761,6 +740,7 @@ leading_lo_surrogate_bif(HiSurr, LoSurr, End) when LoSurr =< End ->
leading_lo_surrogate_bif(_, _, _) -> ok.
utf8_illegal_sequences_bif(Config) when is_list(Config) ->
+ ct:timetrap({minutes,40}), %% valgrind needs a lot
setlimit(10),
ex_utf8_illegal_sequences_bif(Config),
setlimit(default),