aboutsummaryrefslogtreecommitdiffstats
path: root/system/doc
diff options
context:
space:
mode:
authorRaimo Niskanen <[email protected]>2018-04-12 11:01:55 +0200
committerRaimo Niskanen <[email protected]>2018-04-12 11:01:55 +0200
commitb2a68e1e20b9ae41490e5d2777ed5c4f1147b26b (patch)
treed24500f3e4b1d20764926a58aaa8ad441185fbc1 /system/doc
parent3ed7d729cab697b9f668dadb563d629de10f593d (diff)
downloadotp-b2a68e1e20b9ae41490e5d2777ed5c4f1147b26b.tar.gz
otp-b2a68e1e20b9ae41490e5d2777ed5c4f1147b26b.tar.bz2
otp-b2a68e1e20b9ae41490e5d2777ed5c4f1147b26b.zip
Add a 'When to use' section
Diffstat (limited to 'system/doc')
-rw-r--r--system/doc/design_principles/statem.xml107
1 files changed, 89 insertions, 18 deletions
diff --git a/system/doc/design_principles/statem.xml b/system/doc/design_principles/statem.xml
index b44e169a9a..c44f240098 100644
--- a/system/doc/design_principles/statem.xml
+++ b/system/doc/design_principles/statem.xml
@@ -85,6 +85,69 @@ State(S) x Event(E) -> Actions(A), State(S')</pre>
<!-- =================================================================== -->
<section>
+ <marker id="When to use gen_statem" />
+ <title>When to use gen_statem</title>
+ <p>
+ If your process logic is convenient to describe as a state machine,
+ and you want any of these <c>gen_statem</c> key features:
+ </p>
+ <list type="bulleted">
+ <item>
+ Gathered callback code for each state,
+ regardless of
+ <seealso marker="#Event Types">Event Types</seealso>.
+ (such as <em>calls</em>, <em>casts</em> and <em>infos</em>)
+ </item>
+ <item>
+ <seealso marker="#Postponing Events">
+ Postponing Events
+ </seealso>
+ (a substitute for selective receive)
+ </item>
+ <item>
+ <seealso marker="#Inserted Events">
+ Inserted Events
+ </seealso>
+ (in particular purely internal events)
+ </item>
+ <item>
+ <seealso marker="#State Enter Calls">
+ State Enter Calls
+ </seealso>
+ (callback on state entry gathered with the rest
+ of the state callback code)
+ </item>
+ <item>
+ Higher level timeouts
+ (
+ <seealso marker="#State Time-Outs">State Time-Outs</seealso>,
+ <seealso marker="#Event Time-Outs">Event Time-Outs</seealso>
+ or
+ <seealso marker="#Generic Time-Outs">Generic Time-outs</seealso>
+ (named time-outs))
+ </item>
+ </list>
+ <p>
+ If so, or if possibly needed in future versions,
+ then you should consider using <c>gen_statem</c> over
+ <seealso marker="stdlib:gen_server"><c>gen_server</c></seealso>.
+ </p>
+ <p>
+ For simple state machines not needing these fetures
+ <seealso marker="stdlib:gen_server"><c>gen_server</c></seealso>
+ works just fine.
+ It also has got smaller call overhead,
+ but we are talking about something like 2 vs 3.3 microseconds
+ call roundtrip time here, so if the server callback
+ does just a little bit more than just replying,
+ or if the callback is not extremely frequent,
+ that difference will be hard to notice.
+ </p>
+ </section>
+
+<!-- =================================================================== -->
+
+ <section>
<marker id="Callback Module" />
<title>Callback Module</title>
<p>
@@ -160,7 +223,7 @@ State(S) x Event(E) -> Actions(A), State(S')</pre>
</seealso>
function may also return a list containing the callback mode
and the atom <c>state_enter</c> in which case
- <seealso marker="#State Enter Calls">state enter calls</seealso>
+ <seealso marker="#State Enter Calls">State Enter Calls</seealso>
are activated for the callback mode.
</p>
@@ -176,7 +239,7 @@ State(S) x Event(E) -> Actions(A), State(S')</pre>
</p>
<p>
The two
- <seealso marker="#Callback Modes">callback modes</seealso>
+ <seealso marker="#Callback Modes">Callback Modes</seealso>
give different possibilities
and restrictions, but one goal remains:
you want to handle all possible combinations of
@@ -221,6 +284,8 @@ State(S) x Event(E) -> Actions(A), State(S')</pre>
<p>
The mode enables the use of non-atom states, for example,
complex states or even hierarchical states.
+ See section
+ <seealso marker="#Complex State">Complex State</seealso>.
If, for example, a state diagram is largely alike
for the client side and the server side of a protocol,
you can have a state <c>{StateName,server}</c> or
@@ -344,7 +409,10 @@ State(S) x Event(E) -> Actions(A), State(S')</pre>
<item>
<p>
Same as the <c>keep_state</c> or <c>keep_state_and_data</c> values,
- and if <seealso marker="#State Enter Calls">state enter calls</seealso>
+ and if
+ <seealso marker="#State Enter Calls">
+ State Enter Calls
+ </seealso>
are enabled, repeat that call.
</p>
</item>
@@ -379,7 +447,7 @@ State(S) x Event(E) -> Actions(A), State(S')</pre>
<c>Module:init(Args)</c>
</seealso>
callback function is called before any
- <seealso marker="#Event Handler">event handler</seealso>
+ <seealso marker="#Event Handler">Event Handler</seealso>
is called. This function behaves like an event handler
function, but gets its only argument <c>Args</c> from
the <c>gen_statem</c>
@@ -407,8 +475,10 @@ State(S) x Event(E) -> Actions(A), State(S')</pre>
<marker id="State Transition Actions" />
<title>State Transition Actions</title>
<p>
- In the first
- <seealso marker="#Event-Driven State Machines">section</seealso>
+ In the first section
+ <seealso marker="#Event-Driven State Machines">
+ Event-Driven State Machines
+ </seealso>
actions were mentioned as a part of
the general state machine model. These general actions
are implemented with the code that callback module
@@ -644,7 +714,7 @@ StateName(EventType, EventContent, Data) ->
<p>
Since the state enter call is not an event there are restrictions
on the allowed return value and
- <seealso marker="#State Transition Actions">state transition actions</seealso>.
+ <seealso marker="#State Transition Actions">State Transition Actions</seealso>.
You may not change the state,
<seealso marker="#Postponing Events">postpone</seealso>
this non-event, or
@@ -657,7 +727,7 @@ StateName(EventType, EventContent, Data) ->
<p>
You may repeat the state enter call using the <c>{repeat_state,...}</c>
return value from the
- <seealso marker="#Event Handler">event handler</seealso>.
+ <seealso marker="#Event Handler">Event Handler</seealso>.
In this case <c>OldState</c> will also be equal to the current state.
</p>
<p>
@@ -1301,8 +1371,8 @@ open(cast, {button,_}, Data) ->
...
]]></code>
<p>
- An specific generic time-out can just as a
- <seealso marker="#State Time-Outs">state time-out</seealso>
+ Specific generic time-outs can just as
+ <seealso marker="#State Time-Outs">State Time-Outs</seealso>
be restarted or cancelled
by setting it to a new time or <c>infinity</c>.
</p>
@@ -1397,7 +1467,7 @@ open(cast, {button,_}, Data) ->
<p>
Postponing is ordered by the state transition
<seealso marker="#State Transition Actions">
- state transition action
+ State Transition Action
</seealso>
<c>postpone</c>.
</p>
@@ -1422,7 +1492,7 @@ open(cast, {button,_}, Data) ->
(see section
<seealso marker="#Complex State">Complex State</seealso>)
with
- <seealso marker="#Callback Modes">callback mode</seealso>
+ <seealso marker="#Callback Modes">Callback Mode</seealso>
<seealso marker="stdlib:gen_statem#type-callback_mode"><c>handle_event_function</c></seealso>.
If a change in the value changes the set of events that is handled,
then the value should be kept in the State.
@@ -1527,8 +1597,8 @@ do_unlock() ->
</p>
<p>
The
- <seealso marker="#State Transition Action">
- state transition action
+ <seealso marker="#State Transition Actions">
+ State Transition Action
</seealso>
<c>postpone</c> is designed to model
selective receives. A selective receive implicitly postpones
@@ -1555,7 +1625,7 @@ do_unlock() ->
(described in the next section), especially if just
one or a few states has got state enter actions,
this is a perfect use case for the built in
- <seealso marker="#State Enter Calls">state enter calls</seealso>.
+ <seealso marker="#State Enter Calls">State Enter Calls</seealso>.
</p>
<p>
You return a list containing <c>state_enter</c> from your
@@ -1617,7 +1687,7 @@ open(state_timeout, lock, Data) ->
to your own state machine.
This can be done with the
<seealso marker="#State Transition Action">
- state transition action
+ State Transition Action
</seealso>
<c>{next_event,EventType,EventContent}</c>.
</p>
@@ -1970,7 +2040,7 @@ format_status(Opt, [_PDict,State,Data]) ->
<p>
One reason to use this is when you have a state item
that when changed should cancel the
- <seealso marker="#State Time-Outs">state time-out</seealso>,
+ <seealso marker="#State Time-Outs">State Time-Out</seealso>,
or one that affects the event handling
in combination with postponing events.
We will go for the latter and complicate the previous example
@@ -2160,7 +2230,8 @@ handle_event(enter, _OldState, {open,_}, _Data) ->
<c>{open,_}</c> state, which would clutter the code.
</p>
<p>
- Another not uncommon scenario is to use the event time-out
+ Another not uncommon scenario is to use the
+ <seealso marker="#Event Time-Outs">Event Time-Out</seealso>
to trigger hibernation after a certain time of inactivity.
There is also a server start option
<seealso marker="stdlib:gen_statem#type-hibernate_after_opt">