boost-react-native-bundle
Version:
Boost library as in https://sourceforge.net/projects/boost/files/boost/1.57.0/
731 lines (730 loc) • 568 kB
text/xml
<?xml version="1.0" encoding="UTF-8"?>
<?oxygen RNGSchema="http://www.oasis-open.org/docbook/xml/5.0/rng/docbook.rng" type="xml"?>
<book xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0">
<info>
<title>Meta State Machine (MSM)</title>
<author>
<personname>Christophe Henry</personname>
<email>christophe.j.henry@googlemail.com</email>
</author>
<copyright>
<year>2008-2010</year>
<holder>
<phrase> Distributed under the Boost Software License, Version 1.0. (See
accompanying file LICENSE_1_0.txt or copy at <link
xlink:href="http://www.boost.org/LICENSE_1_0.txt"
>http://www.boost.org/LICENSE_1_0.txt</link> ) </phrase>
</holder>
</copyright>
</info>
<preface>
<title>Preface</title>
<para>MSM is a library allowing you to easily and quickly define state machines of very high
performance. From this point, two main questions usually quickly arise, so please allow
me to try answering them upfront.</para>
<para>
<itemizedlist>
<listitem>
<para>When do I need a state machine?</para>
<para>More often that you think. Very often, one defined a state machine
informally without even noticing it. For example, one declares inside a
class some boolean attribute, say to remember that a task has been
completed. Later the boolean actually needs a third value, so it becomes an
int. A few weeks, a second attribute is needed. Then a third. Soon, you find
yourself writing:</para>
<para><code>void incoming_data(data)</code></para>
<para><code>{</code></para>
<para><code> if (data == packet_3 && flag1 == work_done && flag2
> step3)...</code></para>
<para><code>}</code></para>
<para>This starts to look like event processing (contained inside data) if some
stage of the object life has been achieved (but is ugly).</para>
<para>This could be a protocol definition and it is a common use case for state
machines. Another common one is a user interface. The stage of the user's
interaction defines if some button is active, a functionality is available,
etc.</para>
<para>But there are many more use cases if you start looking. Actually, a whole
model-driven development method, Executable UML
(http://en.wikipedia.org/wiki/Executable_UML) specifies its complete dynamic
behavior using state machines. Class diagram, state machine diagrams, and an
action language are all you absolutely need in the Executable UML
world.</para>
</listitem>
<listitem>
<para>Another state machine library? What for?</para>
<para>True, there are many state machine libraries. This should already be an
indication that if you're not using any of them, you might be missing
something. Why should you use this one? Unfortunately, when looking for a
good state machine library, you usually pretty fast hit one or several of
the following snags:<itemizedlist>
<listitem>
<para>speed: "state machines are slow" is usually the first
criticism you might hear. While it is often an excuse not to use
any and instead resort to dirty, hand-written implementations (I
mean, no, yours are not dirty of course, I'm talking about other
developers). MSM removes this often feeble excuse because it is
blazingly fast. Most hand-written implementations will be beaten
by MSM.</para>
</listitem>
<listitem>
<para>ease of use: good argument. If you used another library, you
are probably right. Many state machine definitions will look
similar to:</para>
<para><code>state s1 = new State; // a state</code></para>
<para><code>state s2 = new State; // another state</code></para>
<para><code>event e = new Event; // event</code></para>
<para><code>s1->addTransition(e,s2); // transition s1 ->
s2</code></para>
<para>The more transitions you have, the less readable it is. A long
time ago, there was not so much Java yet, and many electronic
systems were built with a state machine defined by a simple
transition table. You could easily see the whole structure and
immediately see if you forgot some transitions. Thanks to our
new OO techniques, this ease of use was gone. MSM gives you back
the transition table and reduces the noise to the
minimum.</para>
</listitem>
<listitem>
<para>expressiveness: MSM offers several front-ends and constantly
tries to improve state machine definition techniques. For
example, you can define a transition with eUML (one of MSM's
front-ends) as:</para>
<para><code>state1 == state2 + event [condition] /
action</code></para>
<para>This is not simply syntactic sugar. Such a formalized,
readable structure allows easy communication with domain experts
of a software to be constructed. Having domain experts
understand your code will greatly reduce the number of
bugs.</para>
</listitem>
<listitem>
<para>model-driven-development: a common difficulty of a
model-driven development is the complexity of making a
round-trip (generating code from model and then model from
code). This is due to the fact that if a state machine structure
is hard for you to read, chances are that your parsing tool will
also have a hard time. MSM's syntax will hopefully help tool
writers.</para>
</listitem>
<listitem>
<para>features: most developers use only 20% of the richly defined
UML standard. Unfortunately, these are never the same 20% for
all. And so, very likely, one will need something from the
standard which is not implemented. MSM offers a very large part
of the standard, with more on the way.</para>
</listitem>
</itemizedlist></para>
<para>Let us not wait any longer, I hope you will enjoy MSM and have fun with
it!</para>
</listitem>
</itemizedlist>
</para>
</preface>
<part>
<title>User' guide</title>
<chapter>
<title>Founding idea</title>
<para>Let's start with an example taken from the C++ Template Metaprogramming
book:</para>
<programlisting>class player : public state_machine<player>
{
// The list of FSM states enum states { Empty, Open, Stopped, Playing, Paused , initial_state = Empty };
// transition actions
void start_playback(play const&) { std::cout << "player::start_playback\n"; }
void open_drawer(open_close const&) { std::cout << "player::open_drawer\n"; }
// more transition actions
...
typedef player p; // makes transition table cleaner
struct transition_table : mpl::vector11<
// Start Event Target Action
// +---------+------------+-----------+---------------------------+
row< Stopped , play , Playing , &p::start_playback >,
row< Stopped , open_close , Open , &::open_drawer >,
// +---------+------------+-----------+---------------------------+
row< Open , open_close , Empty , &p::close_drawer >,
// +---------+------------+-----------+---------------------------+
row< Empty , open_close , Open , &p::open_drawer >,
row< Empty , cd_detected, Stopped , &p::store_cd_info >,
// +---------+------------+-----------+---------------------------+
row< Playing , stop , Stopped , &p::stop_playback >,
row< Playing , pause , Paused , &p::pause_playback >,
row< Playing , open_close , Open , &p::stop_and_open >,
// +---------+------------+-----------+---------------------------+
row< Paused , play , Playing , &p::resume_playback >,
row< Paused , stop , Stopped , &p::stop_playback >,
row< Paused , open_close , Open , &p::stop_and_open >
// +---------+------------+-----------+---------------------------+
> {};
// Replaces the default no-transition response.
template <class Event>
int no_transition(int state, Event const& e)
{
std::cout << "no transition from state " << state << " on event " << typeid(e).name() << std::endl;
return state;
}
}; </programlisting>
<para>This example is the foundation for the idea driving MSM: a descriptive and
expressive language based on a transition table with as little syntactic noise as
possible, all this while offering as many features from the UML 2.0 standard as
possible. MSM also offers several expressive state machine definition syntaxes with
different trade-offs.</para>
</chapter>
<chapter>
<title>UML Short Guide</title>
<sect1>
<title>What are state machines?</title>
<para>State machines are the description of a thing's lifeline. They describe the
different stages of the lifeline, the events influencing it, and what it does
when a particular event is detected at a particular stage. They offer the
complete specification of the dynamic behavior of the thing.</para>
</sect1>
<sect1>
<title>Concepts</title>
<para>Thinking in terms of state machines is a bit surprising at first, so let us
have a quick glance at the concepts.</para>
<sect2>
<title>State machine, state, transition, event </title>
<para>A state machine is a concrete model describing the behavior of a system.
It is composed of a finite number of states and transitions.</para>
<para>
<inlinemediaobject>
<imageobject>
<imagedata fileref="images/sm.gif"/>
</imageobject>
</inlinemediaobject></para>
<para>A simple state has no sub states. It can have data, entry and exit
behaviors and deferred events. One can provide entry and exit behaviors
(also called actions) to states (or state machines), which are executed
whenever a state is entered or left, no matter how. A state can also have
internal transitions which cause no entry or exit behavior to be called. A
state can mark events as deferred. This means the event cannot be processed
if this state is active, but it must be retained. Next time a state not
deferring this event is active, the event will be processed, as if it had
just been fired. </para>
<para><inlinemediaobject>
<imageobject>
<imagedata fileref="images/state.gif"/>
</imageobject>
</inlinemediaobject></para>
<para>A transition is the switching between active states, triggered by an
event. Actions and guard conditions can be attached to the transition. The
action executes when the transition fires, the guard is a Boolean operation
executed first and which can prevent the transition from firing by returning
false.</para>
<para>
<inlinemediaobject>
<imageobject>
<imagedata fileref="images/transition.jpg"/>
</imageobject>
</inlinemediaobject></para>
<para>An initial state marks the first active state of a state machine. It has
no real existence and neither has the transition originating from it.</para>
<para>
<inlinemediaobject>
<imageobject>
<imagedata fileref="images/init_state.gif"/>
</imageobject>
</inlinemediaobject></para>
</sect2>
<sect2>
<title>Submachines, orthogonal regions, pseudostates </title>
<para>A composite state is a state containing a region or decomposed in two or
more regions. A composite state contains its own set of states and regions. </para>
<para>A submachine is a state machine inserted as a state in another state
machine. The same submachine can be inserted more than once. </para>
<para>Orthogonal regions are parts of a composite state or submachine, each
having its own set of mutually exclusive set of states and transitions. </para>
<para><inlinemediaobject>
<imageobject>
<imagedata fileref="images/regions.gif" width="60%" scalefit="1"/>
</imageobject>
</inlinemediaobject></para>
<para>UML also defines a number of pseudo states, which are considered important
concepts to model, but not enough to make them first-class citizens. The
terminate pseudo state terminates the execution of a state machine (MSM
handles this slightly differently. The state machine is not destroyed but no
further event processing occurs.). </para>
<para><inlinemediaobject>
<imageobject>
<imagedata fileref="images/terminate.gif"/>
</imageobject>
</inlinemediaobject></para>
<para>An exit point pseudo state exits a composite state or a submachine and
forces termination of execution in all contained regions.</para>
<para><inlinemediaobject>
<imageobject>
<imagedata fileref="images/exit.gif" width="60%" scalefit="1"/>
</imageobject>
</inlinemediaobject></para>
<para>An entry point pseudo state allows a kind of controlled entry inside a
composite. Precisely, it connects a transition outside the composite to a
transition inside the composite. An important point is that this mechanism
only allows a single region to be entered. In the above diagram, in region1,
the initial state would become active. </para>
<para><inlinemediaobject>
<imageobject>
<imagedata fileref="images/entry_point.gif"/>
</imageobject>
</inlinemediaobject></para>
<para>There are also two more ways to enter a submachine (apart the obvious and
more common case of a transition terminating on the submachine as shown in
the region case). An explicit entry means that an inside state is the target
of a transition. Unlike with direct entry, no tentative encapsulation is
made, and only one transition is executed. An explicit exit is a transition
from an inner state to a state outside the submachine (not supported by
MSM). I would not recommend using explicit entry or exit. </para>
<para><inlinemediaobject>
<imageobject>
<imagedata fileref="images/explicit.gif"/>
</imageobject>
</inlinemediaobject></para>
<para>The last entry possibility is using fork. A fork is an explicit entry into
one or more regions. Other regions are again activated using their initial
state. </para>
<para><inlinemediaobject>
<imageobject>
<imagedata fileref="images/fork.gif" width="70%" scalefit="1"/>
</imageobject>
</inlinemediaobject></para>
</sect2>
<sect2>
<title>
<command xml:id="uml-history"/>History </title>
<para>UML defines two kinds of history, shallow history and deep history.
Shallow history is a pseudo state representing the most recent substate of a
submachine. A submachine can have at most one shallow history. A transition
with a history pseudo state as target is equivalent to a transition with the
most recent substate as target. And very importantly, only one transition
may originate from the history. Deep history is a shallow history
recursively reactivating the substates of the most recent substate. It is
represented like the shallow history with a star (H* inside a
circle).</para>
<para>
<inlinemediaobject>
<imageobject>
<imagedata fileref="images/history.gif" width="60%" scalefit="1"/>
</imageobject>
</inlinemediaobject></para>
<para>History is not a completely satisfying concept. First of all, there can be
just one history pseudo state and only one transition may originate from it.
So they do not mix well with orthogonal regions as only one region can be
“remembered”. Deep history is even worse and looks like a last-minute
addition. History has to be activated by a transition and only one
transition originates from it, so how to model the transition originating
from the deep history pseudo state and pointing to the most recent substate
of the substate? As a bonus, it is also inflexible and does not accept new
types of histories. Let's face it, history sounds great and is useful in
theory, but the UML version is not quite making the cut. And therefore, MSM
provides a different version of this useful concept. </para>
</sect2>
<sect2>
<title><command xml:id="uml-anonymous"/>Completion transitions / anonymous
transitions</title>
<para>Completion events (or transitions), also called anonymous transitions, are
defined as transitions having no defined event triggering them. This means
that such transitions will immediately fire when a state being the source of
an anonymous transition becomes active, provided that a guard allows it.
They are useful in modeling algorithms as an activity diagram would normally
do. In the real-time world, they have the advantage of making it easier to
estimate how long a periodically executed action will last. For example,
consider the following diagram. </para>
<para><inlinemediaobject>
<imageobject>
<imagedata fileref="images/completion.gif"/>
</imageobject>
</inlinemediaobject></para>
<para>The designer now knows at any time that he will need a maximum of 4
transitions. Being able to estimate how long a transition takes, he can
estimate how much of a time frame he will need to require (real-time tasks
are often executed at regular intervals). If he can also estimate the
duration of actions, he can even use graph algorithms to better estimate his
timing requirements. </para>
</sect2>
<sect2>
<title><command xml:id="UML-internal-transition"/> Internal transitions </title>
<para>Internal transitions are transitions executing in the scope of the active
state, being a simple state or a submachine. One can see them as a
self-transition of this state, without an entry or exit action
called.</para>
</sect2>
<sect2>
<title>
<command xml:id="transition-conflict"/>Conflicting transitions </title>
<para>If, for a given event, several transitions are enabled, they are said to
be in conflict. There are two kinds of conflicts: <itemizedlist>
<listitem>
<para>For a given source state, several transitions are defined,
triggered by the same event. Normally, the guard condition in
each transition defines which one is fired.</para>
</listitem>
<listitem>
<para>The source state is a submachine or simple state and the
conflict is between a transition internal to this state and a
transition triggered by the same event and having as target
another state.</para>
</listitem>
</itemizedlist>The first one is simple; one only needs to define two or more
rows in the transition table, with the same source and trigger, with a
different guard condition. Beware, however, that the UML standard wants
these conditions to be not overlapping. If they do, the standard says
nothing except that this is incorrect, so the implementer is free to
implement it the way he sees fit. In the case of MSM, the transition
appearing last in the transition table gets selected first, if it returns
false (meaning disabled), the library tries with the previous one, and so
on.</para>
<para>
<inlinemediaobject>
<imageobject>
<imagedata fileref="images/conflict1.gif"/>
</imageobject>
</inlinemediaobject></para>
<para>In the second case, UML defines that the most inner transition gets
selected first, which makes sense, otherwise no exit point pseudo state
would be possible (the inner transition brings us to the exit point, from
where the containing state machine can take over). </para>
<para><inlinemediaobject>
<imageobject>
<imagedata fileref="images/conflict2.gif" width="60%" scalefit="1"/>
</imageobject>
</inlinemediaobject></para>
<para>MSM handles both cases itself, so the designer needs only concentrate on
its state machine and the UML subtleties (not overlapping conditions), not
on implementing this behavior himself. </para>
</sect2>
</sect1>
<sect1>
<title>Added concepts</title>
<itemizedlist>
<listitem>
<para>Interrupt states: a terminate state which can be exited if a defined
event is triggered.</para>
</listitem>
<listitem>
<para>Kleene (any) event: a transition with a kleene event will accept any
event as trigger. Unlike a completion transition, an event must be
triggered and the original event is kept accessible in the kleene
event.</para>
</listitem>
</itemizedlist>
</sect1>
<sect1>
<title>State machine glossary</title>
<para>
<itemizedlist>
<listitem>
<para>state machine: the life cycle of a thing. It is made of states,
regions, transitions and processes incoming events.</para>
</listitem>
<listitem>
<para>state: a stage in the life cycle of a state machine. A state (like
a submachine) can have an entry and exit behaviors.</para>
</listitem>
<listitem>
<para>event: an incident provoking (or not) a reaction of the state
machine</para>
</listitem>
<listitem>
<para>transition: a specification of how a state machine reacts to an
event. It specifies a source state, the event triggering the
transition, the target state (which will become the newly active
state if the transition is triggered), guard and actions.</para>
</listitem>
<listitem>
<para>action: an operation executed during the triggering of the
transition.</para>
</listitem>
<listitem>
<para>guard: a boolean operation being able to prevent the triggering of
a transition which would otherwise fire.</para>
</listitem>
<listitem>
<para>transition table: representation of a state machine. A state
machine diagram is a graphical, but incomplete representation of the
same model. A transition table, on the other hand, is a complete
representation.</para>
</listitem>
<listitem>
<para>initial state: The state in which the state machine starts. Having
several orthogonal regions means having as many initial
states.</para>
</listitem>
<listitem>
<para>submachine: A submachine is a state machine inserted as a state in
another state machine and can be found several times in a same state
machine.</para>
</listitem>
<listitem>
<para>orthogonal regions: (logical) parallel flow of execution of a
state machine. Every region of a state machine gets a chance to
process an incoming event.</para>
</listitem>
<listitem>
<para>terminate pseudo-state: when this state becomes active, it
terminates the execution of the whole state machine. MSM does not
destroy the state machine as required by the UML standard, however,
which lets you keep all the state machine's data.</para>
</listitem>
<listitem>
<para>entry/exit pseudo state: defined for submachines and are defined
as a connection between a transition outside of the submachine and a
transition inside the submachine. It is a way to enter or leave a
submachine through a predefined point.</para>
</listitem>
<listitem>
<para>fork: a fork allows explicit entry into several orthogonal regions
of a submachine.</para>
</listitem>
<listitem>
<para>history: a history is a way to remember the active state of a
submachine so that the submachine can proceed in its last active
state next time it becomes active.</para>
</listitem>
<listitem>
<para>completion events (also called completion/anonymous transitions):
when a transition has no named event triggering it, it automatically
fires when the source state is active, unless a guard forbids
it.</para>
</listitem>
<listitem>
<para>transition conflict: a conflict is present if for a given source
state and incoming event, several transitions are possible. UML
specifies that guard conditions have to solve the conflict.</para>
</listitem>
<listitem>
<para>internal transitions: transition from a state to itself without
having exit and entry actions being called.</para>
</listitem>
</itemizedlist>
</para>
</sect1>
</chapter>
<chapter>
<title>Tutorial</title>
<sect1>
<title>Design</title>
<para>MSM is divided between front–ends and back-ends. At the moment, there is just
one back-end. On the front-end side, you will find three of them which are as
many state machine description languages, with many more possible. For potential
language writers, this document contains a <link
xlink:href="#internals-front-back-interface">description of the interface
between front-end and back-end</link>.</para>
<para>The first front-end is an adaptation of the example provided in the <link
xlink:href="http://boostpro.com/mplbook">MPL book</link> with actions
defined as pointers to state or state machine methods. The second one is based
on functors. The third, eUML (embedded UML) is an experimental language based on
Boost.Proto and Boost.Typeof and hiding most of the metaprogramming to increase
readability. Both eUML and the functor front-end also offer a functional library
(a bit like Boost.Phoenix) for use as action language (UML defining
none).</para>
</sect1>
<sect1>
<title><command xml:id="basic-front-end"/>Basic front-end</title>
<para>This is the historical front-end, inherited from the MPL book. It provides a
transition table made of rows of different names and functionality. Actions and
guards are defined as methods and referenced through a pointer in the
transition. This front-end provides a simple interface making easy state
machines easy to define, but more complex state machines a bit harder.</para>
<sect2>
<title>A simple example</title>
<para>Let us have a look at a state machine diagram of the founding
example:</para>
<para><inlinemediaobject>
<imageobject>
<imagedata fileref="images/SimpleTutorial.jpg" width="60%"
scalefit="1"/>
</imageobject>
</inlinemediaobject></para>
<para>We are now going to build it with MSM's basic front-end. An <link
xlink:href="examples/SimpleTutorial.cpp">implementation</link> is also
provided.</para>
</sect2>
<sect2>
<title>Transition table</title>
<para>As previously stated, MSM is based on the transition table, so let us
define one:</para>
<programlisting>
struct transition_table : mpl::vector<
// Start Event Target Action Guard
// +---------+------------+-----------+---------------------------+----------------------------+
a_row< Stopped , play , Playing , &player_::start_playback >,
a_row< Stopped , open_close , Open , &player_::open_drawer >,
_row< Stopped , stop , Stopped >,
// +---------+------------+-----------+---------------------------+----------------------------+
a_row< Open , open_close , Empty , &player_::close_drawer >,
// +---------+------------+-----------+---------------------------+----------------------------+
a_row< Empty , open_close , Open , &player_::open_drawer >,
row< Empty , cd_detected, Stopped , &player_::store_cd_info , &player_::good_disk_format >,
row< Empty , cd_detected, Playing , &player_::store_cd_info , &player_::auto_start >,
// +---------+------------+-----------+---------------------------+----------------------------+
a_row< Playing , stop , Stopped , &player_::stop_playback >,
a_row< Playing , pause , Paused , &player_::pause_playback >,
a_row< Playing , open_close , Open , &player_::stop_and_open >,
// +---------+------------+-----------+---------------------------+----------------------------+
a_row< Paused , end_pause , Playing , &player_::resume_playback >,
a_row< Paused , stop , Stopped , &player_::stop_playback >,
a_row< Paused , open_close , Open , &player_::stop_and_open >
// +---------+------------+-----------+---------------------------+----------------------------+
> {};
</programlisting>
<para>You will notice that this is almost exactly our founding example. The only
change in the transition table is the different types of transitions (rows).
The founding example forces one to define an action method and offers no
guards. You have 4 basic row types:<itemizedlist>
<listitem>
<para><code>row</code> takes 5 arguments: start state, event, target
state, action and guard.</para>
</listitem>
<listitem>
<para><code>a_row</code> (“a” for action) allows defining only the
action and omit the guard condition.</para>
</listitem>
<listitem>
<para><code>g_row</code> (“g” for guard) allows omitting the action
behavior and defining only the guard.</para>
</listitem>
<listitem>
<para><code>_row</code> allows omitting action and guard.</para>
</listitem>
</itemizedlist></para>
<para>The signature for an action methods is void method_name (event
const&), for example:</para>
<programlisting>void stop_playback(stop const&)</programlisting>
<para>Action methods return nothing and take the argument as const reference. Of
course nothing forbids you from using the same action for several
events:</para>
<programlisting>template <class Event> void stop_playback(Eventconst&)</programlisting>
<para>Guards have as only difference the return value, which is a
boolean:</para>
<programlisting>bool good_disk_format(cd_detected const& evt)</programlisting>
<para>The transition table is actually a MPL vector (or list), which brings the
limitation that the default maximum size of the table is 20. If you need
more transitions, overriding this default behavior is necessary, so you need
to add before any header:</para>
<programlisting>#define BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
#define BOOST_MPL_LIMIT_VECTOR_SIZE 30 //or whatever you need
#define BOOST_MPL_LIMIT_MAP_SIZE 30 //or whatever you need </programlisting>
<para>The other limitation is that the MPL types are defined only up to 50
entries. For the moment, the only solution to achieve more is to add headers
to the MPL (luckily, this is not very complicated).</para>
</sect2>
<sect2>
<title>Defining states with entry/exit actions</title>
<para>While states were enums in the MPL book, they now are classes, which
allows them to hold data, provide entry, exit behaviors and be reusable (as
they do not know anything about the containing state machine). To define a
state, inherit from the desired state type. You will mainly use simple
states:</para>
<para>struct Empty : public msm::front::state<> {};</para>
<para>They can optionally provide entry and exit behaviors:</para>
<programlisting language="C++">
struct Empty : public msm::front::state<>
{
template <class Event, class Fsm>
void on_entry(Event const&, Fsm& )
{std::cout <<"entering: Empty" << std::endl;}
template <class Event, class Fsm>
void on_exit(Event const&, Fsm& )
{std::cout <<"leaving: Empty" << std::endl;}
};
</programlisting>
<para>Notice how the entry and exit behaviors are templatized on the event and
state machine. Being generic facilitates reuse. There are more state types
(terminate, interrupt, pseudo states, etc.) corresponding to the UML
standard state types. These will be described in details in the next
sections.</para>
</sect2>
<sect2>
<title>What do you actually do inside actions / guards?</title>
<para>State machines define a structure and important parts of the complete
behavior, but not all. For example if you need to send a rocket to Alpha
Centauri, you can have a transition to a state "SendRocketToAlphaCentauri"
but no code actually sending the rocket. This is where you need actions. So
a simple action could be:</para>
<programlisting>template <class Fire> void send_rocket(Fire const&)
{
fire_rocket();
}</programlisting>
<para>Ok, this was simple. Now, we might want to give a direction. Let us suppose
this information is externally given when needed, it makes sense do use the
event for this:</para>
<programlisting>// Event
struct Fire {Direction direction;};
template <class Fire> void send_rocket(Fire const& evt)
{
fire_rocket(evt.direction);
}</programlisting>
<para>We might want to calculate the direction based not only on external data
but also on data accumulated during previous work. In this case, you might
want to have this data in the state machine itself. As transition actions
are members of the front-end, you can directly access the data:</para>
<programlisting>// Event
struct Fire {Direction direction;};
//front-end definition, see down
struct launcher_ : public msm::front::state_machine_def<launcher_>{
Data current_calculation;
template <class Fire> void send_rocket(Fire const& evt)
{
fire_rocket(evt.direction, current_calculation);
}
...
};</programlisting>
<para>Entry and exit actions represent a behavior common to a state, no matter
through which transition it is entered or left. States being reusable, it
might make sense to locate your data there instead of in the state machine,
to maximize reuse and make code more readable. Entry and exit actions have
access to the state data (being state members) but also to the event and
state machine, like transition actions. This happens through the Event and
Fsm template parameters:</para>
<programlisting>struct Launching : public msm::front::state<>
{
template <class Event, class Fsm>
void on_entry(Event const& evt, Fsm& fsm)
{
fire_rocket(evt.direction, fsm.current_calculation);
}
};</programlisting>
<para>Exit actions are also ideal for clanup when the state becomes
inactive.</para>
<para>Another possible use of the entry action is to pass data to substates /
submachines. Launching is a substate containing a <code>data</code> attribute:</para>
<programlisting>struct launcher_ : public msm::front::state_machine_def<launcher_>{
Data current_calculation;
// state machines also have entry/exit actions
template <class Event, class Fsm>
void on_entry(Event const& evt, Fsm& fsm)
{
launcher_::Launching& s = fsm.get_state<launcher_::Launching&>();
s.data = fsm.current_calculation;
}
...
};</programlisting>
<para>The <command xlink:href="#backend-fsm-constructor-args">set_states</command> back-end method allows you to replace a complete
state.</para>
<para>The <command xlink:href="#functor-front-end-actions">functor</command> front-end and eUML offer more capabilities.</para>
<para>However, this basic front-end also has special capabilities using the row2
/ irow2 transitions.<command xlink:href="#basic-row2">_row2, a_row2, row2,
g_row2, a_irow2, irow2, g_irow2</command> let you call an action located
in any state of the current fsm or in the front-end itself, thus letting you
place useful data anywhere you see fit.</para>
<para>It is sometimes desirable to generate new events for the state machine
inside actions. Since the process_event method belongs to the back end, you
first need to gain a reference to it. The back end derives from the front
end, so one way of doing this is to use a cast:</para>
<programlisting>struct launcher_ : public msm::front::state_machine_def<launcher_>{
template <class Fire> void send_rocket(Fire const& evt)
{
fire_rocket();
msm::back::state_machine<launcher_> &fsm = static_cast<msm::back::state_machine<launcher_> &>(*this);
fsm.process_event(rocket_launched());
}
...
};</programlisting>
<para>The same can be implemented inside entry/exit actions. Admittedly, this is
a bit awkward. A more natural mechanism is available using the <command
xlink:href="#functor-front-end-actions">functor</command>
front-end.</para>
</sect2>
<sect2>
<title>Defining a simple state machine</title>
<para>Declaring a state machine is straightforward and is done with a high
signal / noise ratio. In our player e