From 61935c77915a8e206a82cba1c9c9f64be462905d Mon Sep 17 00:00:00 2001
From: Raimo Niskanen
Established Automata Theory does not deal much with
- how a state transition is triggered,
+ how a state transition is triggered,
but assumes that the output is a function
of the input (and the state) and that they are
some kind of values.
For an Event-Driven State Machine, the input is an event
- that triggers a state transition and the output
- is actions executed during the state transition.
+ that triggers a state transition and the output
+ is actions executed during the state transition.
It can analogously to the mathematical model of a
- Finite-State Machine be described as
+ Finite State Machine be described as
a set of relations of the following form:
These relations are interpreted as follows:
+
+ These relations are interpreted as follows:
if we are in state
+ In
As
- The callback module contains functions that implement
+ The callback module contains functions that implement
the state machine.
When an event occurs,
the
- The
- The callback mode is selected at server start
+ The callback mode is selected at server start
and may be changed with a code upgrade/downgrade.
See the section
-
- The callback mode is selected by implementing
+ The callback mode is selected by implementing
a mandatory callback function
The
The two
-
- Which callback function that handles an event
- depends on the callback mode:
+ The state callback is the callback function
+ that handles an event in the current state,
+ and which function that is depends on the callback mode:
See section
-
- State enter calls are also handled by the event handler and have
- slightly different arguments. See the section
+ State enter calls are also handled by the event handler
+ and have slightly different arguments. See section
- The event handler return values are defined in the description of
+ The state callback return values
+ are defined in the description of
Set next state and update the server data.
- If the
See section
-
- If
Same as the
+ If these return values are used from a
+ state enter call the
Same as the
In the first section
- There are more specific state-transition actions
+ There are more specific transition actions
that a callback function can command the
State(S) x Event(E) -> Actions(A), State(S')
-
@@ -435,7 +466,10 @@ State(S) x Event(E) -> Actions(A), State(S')
Events are categorized in different
-
- The following is a complete list of event types and where + The following is a complete list of event types and where they come from:
The
@@ -714,33 +748,35 @@ StateName(EventType, EventContent, Data) -> ... code for actions here ... {next_state, NewStateName, NewData}.
- Since the state enter call is not an event there are restrictions
+ Since the state enter call is not an event there are restrictions
on the allowed return value and
- The first state that is entered will get a state enter call
+ The first state that is entered
+ will get a state enter call
with
- You may repeat the state enter call using the
Depending on how your state machine is specified,
- this can be a very useful feature,
- but it forces you to handle the state enter calls in all states.
+ this can be a very useful feature, but it forces you to handle
+ the state enter calls in all states.
See also the
This code lock state machine can be implemented using
-
-
The second argument, ?MODULE , is the name of
- the callback module, that is, the module where the callback
+ the callback module, that is,
+ the module where the callback
functions are located, which is this module.
@@ -935,7 +972,7 @@ init(Code) ->
Module:callback_mode/0
selects the
CallbackMode
- for the callback module, in this case
+ for the callback module, in this case
state_functions .
That is, each state has got its own handler function:
@@ -1051,11 +1088,11 @@ open(state_timeout, lock, Data) ->
]]>
The timer for a state time-out is automatically cancelled
- when the state machine changes states. You can restart
- a state time-out by setting it to a new time, which cancels
- the running timer and starts a new. This implies that
- you can cancel a state time-out by restarting it with
- time
- If the common event handler needs to know the current state
+ If the common state callback needs to know the current state
a function
... ;
-
- One Event Handler
+
+ One State Callback
If
- Callback Mode
+ callback mode
handle_event_function is used,
all events are handled in
@@ -1289,7 +1326,10 @@ stop() ->
You get either an event or a time-out, but not both.
- It is ordered by the state transition action
+ It is ordered by the
+
+ transition action
+
{timeout,Time,EventContent} , or just an integer Time ,
even without the enclosing actions list
(the latter is a form inherited from gen_fsm .
@@ -1315,7 +1355,7 @@ locked(
]]>
Whenever we receive a button event we start an event time-out
- of 30 seconds, and if we get an event type
@@ -1327,7 +1367,7 @@ locked(
Note that an event time-out does not work well with
- when you have for example a status call as in
+ when you have for example a status call as in section
Specific generic time-outs can just as
-
- In this particular case we do not need to cancel the timeout
- since the timeout event is the only possible reason to
- change the state from
Instead of bothering with when to cancel a time-out, @@ -1442,7 +1482,7 @@ open(cast, {button,_}, Data) -> ]]>
Removing the
If you want to ignore a particular event in the current state
and handle it in a future state, you can postpone the event.
- A postponed event is retried after the state has
- changed, that is,
- Postponing is ordered by the state transition
-
- Since a postponed event is only retried after a state change,
+ Since a postponed event is only retried
+ after a state change,
you have to think about where to keep a state data item.
You can keep it in the server
The
-
Both mechanisms have the same theoretical
@@ -1638,14 +1679,17 @@ 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
-
You return a list containing
It can sometimes be beneficial to be able to generate events
to your own state machine.
This can be done with the
-
- State Transition Action
+
+ transition action
{next_event,EventType,EventContent} .
@@ -1731,11 +1775,9 @@ open(state_timeout, lock, Data) ->
A variant of this is to use a
-
- Complex State
-
+ complex state
with
- One Event Handler .
+ one state callback .
The state is then modeled with for example a tuple
{MainFSMState,SubFSMState} .
@@ -1795,7 +1837,7 @@ open(internal, {button,_}, Data) ->
Example Revisited
This section includes the example after most of the mentioned
- modifications and some more using state enter calls,
+ modifications and some more using state enter calls,
which deserves a new state diagram:
+
+
+
+ Time-outs
+
+ Time-outs in gen_statem are started from a
+
+ transition action
+
+ during a state transition that is when exiting from the
+ state callback .
+
+
+ There are 3 types of time-outs in gen_statem :
+
+
+
+
+ state_timeout
+
+
+ -
+ There is one
+
State Time-Out
+ that is automatically cancelled by a state change.
+
+
+
+ {timeout, Name}
+
+
+ -
+ There are any number of
+
Generic Time-Outs
+ differing by their Name .
+ They have no automatic cancelling.
+
+
+
+ timeout
+
+
+ -
+ There is one
+
Event Time-Out
+ that is automatically cancelled by any event.
+ Note that
+ postponed
+ and
+ inserted
+ events cancel this timeout just as external events.
+
+
+
+ When a time-out is started any running time-out with the same tag,
+ state_timeout , {timeout, Name} or timeout ,
+ is cancelled, that is the time-out is restarted with the new time.
+
+
+ All time-outs has got an EventContent that is part of the
+
+ transition action
+
+ that starts the time-out.
+ Different EventContent s does not create different time-outs.
+ The EventContent is delivered to the
+ state callback
+ when the time-out expires.
+
+
+
+ Cancelling a Time-Out
+
+ If a time-out is started with the time infinity it will
+ never time out, in fact it will not even be started, and any
+ running time-out with the same tag will be cancelled.
+ The EventContent will in this case be ignored,
+ so why not set it to undefined .
+
+
+
+
+ Time-Out Zero
+
+ If a time-out is started with the time 0 it will
+ actually not be started. Instead the time-out event will
+ immediately be inserted to be processed after any events
+ already enqueued, and before any not yet received external events.
+ Note that some time-outs are automatically cancelled
+ so if you for example combine
+ postponing
+ an event in a state change with starting an
+ event time-out
+ with time 0 there will be no timeout event inserted
+ since the event time-out is cancelled by the postponed
+ event that is delivered due to the state change.
+
+
+
+
+
--
cgit v1.2.3