mirror of
https://github.com/boostorg/msm.git
synced 2026-02-18 14:12:31 +00:00
1302 lines
144 KiB
HTML
1302 lines
144 KiB
HTML
<html><head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
|
<title>User's Guide</title><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="index.html" title="Meta State Machine (MSM)"><link rel="up" href="index.html" title="Meta State Machine (MSM)"><link rel="prev" href="ar01s03.html" title="UML Short Guide"><link rel="next" href="ar01s05.html" title="Performance / Compilers"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">User's Guide</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="ar01s03.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="ar01s05.html">Next</a></td></tr></table><hr></div><div class="sect1" title="User's Guide"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e402"></a>User's Guide</h2></div></div></div><div class="sect2" title="Design"><div class="titlepage"><div><div><h3 class="title"><a name="d0e405"></a>Design</h3></div></div></div><p>Msm is divided between front–ends and back-ends. At the moment, there is just one
|
|
back-end. On the front-end side, there is more to see. Msm offers several state
|
|
machine description languages with many more possible. Now, everybody can build his
|
|
own description language (in case one gets bored with the ones provided) without
|
|
changes to the library. For who feels like being a language writer this document
|
|
adds a description of the interface between front-end and back-end.TODO.</p><p>There are, at the moment, three main front-ends. The basic one is an adaptation of
|
|
the example provided in the MPL book (TODO add 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).</p></div><div class="sect2" title="Basic front-end"><div class="titlepage"><div><div><h3 class="title"><a name="d0e412"></a>Basic front-end</h3></div></div></div><p>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 easier to
|
|
define, but more complex state machines a bit harder. It also is slightly slower
|
|
than the functor and eUML front-ends (about 20%). Not that it does more, it simply
|
|
seems that the compiler better optimizes the functor actions.</p><div class="sect3" title="A simple example"><div class="titlepage"><div><div><h4 class="title"><a name="d0e417"></a>A simple example</h4></div></div></div><p>Let us have a look at a state machine diagram of the founding example:</p><p><span class="inlinemediaobject"><img src="../images/SimpleTutorial.jpg"></span></p><p>We are now going to build it with MSM's basic front-end. An <a class="link" href="examples/SimpleTutorial.cpp" target="_top">example</a> is also
|
|
provided.</p></div><div class="sect3" title="Transition table"><div class="titlepage"><div><div><h4 class="title"><a name="d0e431"></a>Transition table</h4></div></div></div><p>As previously stated, MSM is based on the transition table, so let us define
|
|
one:</p><p>struct transition_table : mpl::vector<</p><p>
|
|
</p><table frame="void" id="d0e440"><tbody><tr>
|
|
<td>//</td>
|
|
<td>Start</td>
|
|
<td>Event</td>
|
|
<td>Next</td>
|
|
<td>Action</td>
|
|
<td>Guard</td>
|
|
<td> </td>
|
|
</tr><tr>
|
|
<td>//</td>
|
|
<td>+---------+</td>
|
|
<td>-------------+</td>
|
|
<td>---------+</td>
|
|
<td>---------------------+</td>
|
|
<td>----------------------+</td>
|
|
<td> </td>
|
|
</tr><tr>
|
|
<td>a_row <</td>
|
|
<td>Stopped ,</td>
|
|
<td>play,</td>
|
|
<td>Playing,</td>
|
|
<td>&player_::start_playback</td>
|
|
<td> </td>
|
|
<td>>,</td>
|
|
</tr><tr>
|
|
<td>a_row <</td>
|
|
<td>Stopped ,</td>
|
|
<td>open_close,</td>
|
|
<td>Open,</td>
|
|
<td>&player_::open_drawer</td>
|
|
<td> </td>
|
|
<td>>,</td>
|
|
</tr><tr>
|
|
<td>_row <</td>
|
|
<td>Stopped ,</td>
|
|
<td>stop,</td>
|
|
<td>Stopped</td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td>>,</td>
|
|
</tr><tr>
|
|
<td>//</td>
|
|
<td>+---------</td>
|
|
<td>-------------+</td>
|
|
<td>---------+</td>
|
|
<td>---------------------+</td>
|
|
<td>----------------------+</td>
|
|
<td> </td>
|
|
</tr><tr>
|
|
<td>a_row <</td>
|
|
<td>Open ,</td>
|
|
<td>open_close ,</td>
|
|
<td>Empty ,</td>
|
|
<td>&player_::close_drawer</td>
|
|
<td> </td>
|
|
<td>>,</td>
|
|
</tr><tr>
|
|
<td>//</td>
|
|
<td>+---------+</td>
|
|
<td>-------------+</td>
|
|
<td>---------+</td>
|
|
<td>---------------------+</td>
|
|
<td>----------------------+</td>
|
|
<td> </td>
|
|
</tr><tr>
|
|
<td>a_row <</td>
|
|
<td>Empty ,</td>
|
|
<td>open_close ,</td>
|
|
<td>Open ,</td>
|
|
<td>&player_::open_drawer</td>
|
|
<td> </td>
|
|
<td>>,</td>
|
|
</tr><tr>
|
|
<td>row <</td>
|
|
<td>Empty ,</td>
|
|
<td>cd_detected ,</td>
|
|
<td>Stopped ,</td>
|
|
<td>&player_::store_cd_info ,</td>
|
|
<td>&player_::good_disk_format</td>
|
|
<td>>,</td>
|
|
</tr><tr>
|
|
<td>row <</td>
|
|
<td>Empty ,</td>
|
|
<td>cd_detected ,</td>
|
|
<td>Playing ,</td>
|
|
<td>&player_::store_cd_info ,</td>
|
|
<td>&player_::auto_start</td>
|
|
<td>>,</td>
|
|
</tr><tr>
|
|
<td>//</td>
|
|
<td>+---------+</td>
|
|
<td>-------------+</td>
|
|
<td>---------+</td>
|
|
<td>---------------------+</td>
|
|
<td>----------------------+</td>
|
|
<td> </td>
|
|
</tr><tr>
|
|
<td>a_row <</td>
|
|
<td>Playing ,</td>
|
|
<td>stop ,</td>
|
|
<td>Stopped ,</td>
|
|
<td>&player_::stop_playback</td>
|
|
<td> </td>
|
|
<td>>,</td>
|
|
</tr><tr>
|
|
<td>a_row <</td>
|
|
<td>Playing ,</td>
|
|
<td>pause ,</td>
|
|
<td>Paused ,</td>
|
|
<td>&player_::pause_playback</td>
|
|
<td> </td>
|
|
<td>>,</td>
|
|
</tr><tr>
|
|
<td>a_row <</td>
|
|
<td>Playing ,</td>
|
|
<td>open_close ,</td>
|
|
<td>Open ,</td>
|
|
<td>&player_::stop_and_open</td>
|
|
<td> </td>
|
|
<td>>,</td>
|
|
</tr><tr>
|
|
<td>//</td>
|
|
<td>+---------+</td>
|
|
<td>-------------+</td>
|
|
<td>---------+</td>
|
|
<td>---------------------+</td>
|
|
<td>----------------------+</td>
|
|
<td> </td>
|
|
</tr><tr>
|
|
<td>a_row <</td>
|
|
<td> Paused ,</td>
|
|
<td>end_pause ,</td>
|
|
<td>Playing ,</td>
|
|
<td>&player_::resume_playback</td>
|
|
<td> </td>
|
|
<td>>,</td>
|
|
</tr><tr>
|
|
<td>a_row <</td>
|
|
<td> Paused ,</td>
|
|
<td>stop ,</td>
|
|
<td>Stopped ,</td>
|
|
<td>&player_::stop_playback</td>
|
|
<td> </td>
|
|
<td>>,</td>
|
|
</tr><tr>
|
|
<td>a_row <</td>
|
|
<td> Paused ,</td>
|
|
<td>open_close ,</td>
|
|
<td>Open ,</td>
|
|
<td>&player_::stop_and_open</td>
|
|
<td> </td>
|
|
<td>></td>
|
|
</tr><tr>
|
|
<td>//</td>
|
|
<td>+---------+</td>
|
|
<td>-------------+</td>
|
|
<td>---------+</td>
|
|
<td>---------------------+</td>
|
|
<td>----------------------+</td>
|
|
<td> </td>
|
|
</tr><tr>
|
|
<td>> {};</td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
</tr></tbody></table><p>
|
|
</p><p>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:</p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p><code class="code">row</code> takes 5 arguments: start state, event, next
|
|
state, action and guard.</p></li><li class="listitem"><p><code class="code">a_row</code> (“a” for action) allows defining only the
|
|
action and omit the guard condition.</p></li><li class="listitem"><p><code class="code">g_row</code> (“g” for guard) allows omitting the action
|
|
method and defining only the guard.</p></li><li class="listitem"><p><code class="code">_row</code> allows omitting action and guard methods.</p></li></ul></div><p>The signature for action methods is:</p><p><code class="code">void stop_playback(stop const&)</code></p><p>Action methods return nothing and take the argument as const reference. Of
|
|
course nothing forbids you from defining an action for several events:</p><p><code class="code">template <class Event> void stop_playback(Event
|
|
const&)</code></p><p>Guards have as only difference the return value, which is a boolean:</p><p><code class="code">bool good_disk_format(cd_detected const& evt)</code></p><p>The transition table is actually a MPL vector (or list), which brings a
|
|
limitation that the default maximum size of the table is 20. If you need more
|
|
transitions, overriding this default behavior is necessary, for example add
|
|
before any header:</p><p><code class="code">#define BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS </code></p><p><code class="code">#define BOOST_MPL_LIMIT_VECTOR_SIZE 30 // or whatever you need
|
|
</code></p><p><code class="code">#define BOOST_MPL_LIMIT_MAP_SIZE 30 // or whatever you need
|
|
</code></p><p>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).TODO add them</p></div><div class="sect3" title="Defining states with entry/exit actions"><div class="titlepage"><div><div><h4 class="title"><a name="d0e977"></a>Defining states with entry/exit actions</h4></div></div></div><p>While states were enums in the MPL book, they now are structs, which allows
|
|
them to hold data, provide entry, exit actions, different behaviors and be
|
|
reusable (as they do not know anything about the containing state machine). To
|
|
define a state, inherit from the correct state type:</p><p>struct Empty : public msm::front::state<> {};</p><p>They can optionally provide entry and exit behaviors:</p><p><code class="code">struct Empty : public msm::front::state<> {</code></p><p><code class="code">template <class Event, class Fsm> </code></p><p><code class="code">void on_entry(Event const&, Fsm& ) {std::cout <<
|
|
"entering: Empty" << std::endl;} </code></p><p><code class="code">template <class Event, class Fsm> </code></p><p><code class="code">void on_exit(Event const&, Fsm& ) {std::cout << "leaving:
|
|
Empty" << std::endl;} </code></p><p><code class="code">};</code></p><p>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 pages.</p></div><div class="sect3" title="Defining a simple state machine"><div class="titlepage"><div><div><h4 class="title"><a name="d0e1006"></a>Defining a simple state machine</h4></div></div></div><p>Declaring a state machine is straightforward and is done with a high signal /
|
|
noise ratio. In our player example, we declare the state machine as:</p><p><code class="code">struct player_ : public msm::front::state_machine_def<player_>{ /*
|
|
see below */}</code></p><p>This declares a state machine using the basic front-end. We now declare inside
|
|
the state machine structure the initial state:</p><p><code class="code">typedef Empty initial_state;</code></p><p>And that is about all of what is absolutely needed. In the example, the states
|
|
are declared inside the state machine for readability but this is not a
|
|
requirements, states can be declared wherever you see fit.</p><p>All what is left to us is to pick a back-end (which is quite simple as there
|
|
is only one at the moment):</p><p><code class="code">typedef msm::back::state_machine<player_> player;</code></p><p>You now have a ready-to-use state machine with entry/exit actions, guards,
|
|
transition actions, a message queue so that processing an event can generate
|
|
another event. The state machine also adapted itself to your need and removed
|
|
almost all features we didn't use in this simple example. Note that this is not
|
|
per default the faster possible state machine. See the section "getting more
|
|
speed" to know how to get the maximum speed. In a nutshell, MSM cannot know
|
|
about your usage of some features so you will have to explicitly tell it.</p><p>TODO no_transition TODO start fct</p></div><div class="sect3" title="Defining a submachine"><div class="titlepage"><div><div><h4 class="title"><a name="d0e1030"></a>Defining a submachine</h4></div></div></div><p>We now want to extend our last state machine by making the Playing state a
|
|
state machine itself (a submachine).</p><p><span class="inlinemediaobject"><img src="../images/CompositeTutorial.jpg"></span></p><p>Again, an <a class="link" href="examples/CompositeTutorial.cpp" target="_top">example</a> is
|
|
also provided.</p><p>A submachine really is a state machine itself, so we declare Playing as such,
|
|
choosing a front-end and a back-end:</p><p><code class="code">struct Playing_ : public msm::Front::state_machine_def<Playing_>{...}
|
|
</code></p><p><code class="code">typedef msm::back::state_machine<Playing_> Playing;</code></p><p>Like for any state machine, one also needs a transition table and an initial
|
|
state:</p><p>struct transition_table : mpl::vector<</p><table id="d0e1056"><tbody><tr>
|
|
<td>//</td>
|
|
<td>Start</td>
|
|
<td>Event</td>
|
|
<td>Next</td>
|
|
<td>Action</td>
|
|
<td>Guard</td>
|
|
<td> </td>
|
|
</tr><tr>
|
|
<td>//</td>
|
|
<td>+---------+</td>
|
|
<td>-------------+</td>
|
|
<td>---------+</td>
|
|
<td>------------------------------+</td>
|
|
<td>----------------------+</td>
|
|
<td> </td>
|
|
</tr><tr>
|
|
<td>a_row <</td>
|
|
<td>Song1 ,</td>
|
|
<td>NextSong,</td>
|
|
<td>Song2,</td>
|
|
<td>&Playing_::start_next_song </td>
|
|
<td> </td>
|
|
<td>>,</td>
|
|
</tr><tr>
|
|
<td>a_row <</td>
|
|
<td>Song2 ,</td>
|
|
<td>PreviousSong,</td>
|
|
<td>Song1,</td>
|
|
<td>&Playing_::start_prev_song </td>
|
|
<td> </td>
|
|
<td>>,</td>
|
|
</tr><tr>
|
|
<td>a_row <</td>
|
|
<td>Song2 ,</td>
|
|
<td>NextSong,</td>
|
|
<td>Song3,</td>
|
|
<td>&Playing_::start_next_song </td>
|
|
<td> </td>
|
|
<td>>,</td>
|
|
</tr><tr>
|
|
<td>a_row <</td>
|
|
<td>Song3 ,</td>
|
|
<td>PreviousSong ,</td>
|
|
<td>Song2 ,</td>
|
|
<td>&Playing_::start_prev_song </td>
|
|
<td> </td>
|
|
<td>></td>
|
|
</tr><tr>
|
|
<td>//</td>
|
|
<td>+---------+</td>
|
|
<td>-------------+</td>
|
|
<td>---------+</td>
|
|
<td>------------------------------+</td>
|
|
<td>----------------------+</td>
|
|
<td> </td>
|
|
</tr><tr>
|
|
<td>> {};</td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
</tr></tbody></table><p><code class="code">typedef Song1 initial_state; </code></p><p>This is about all you need to do. MSM will now automatically recognize Playing
|
|
as a submachine and all events handled by Playing (NextSong and PreviousSong)
|
|
will now be automatically forwarded to Playing whenever this state is active.
|
|
All other state machine features described later are also available.</p></div><div class="sect3" title="Orthogonal regions, terminate state, event deferring"><div class="titlepage"><div><div><h4 class="title"><a name="d0e1247"></a>Orthogonal regions, terminate state, event deferring</h4></div></div></div><p>It is a very common problem in many state machines to have to handle errors.
|
|
It usually involves defining a transition from all the states to a special error
|
|
state. Translation: not fun. It is also not practical to find from which state
|
|
the error originated. The following diagram shows an example of what clearly
|
|
becomes not very readable:</p><p><span class="inlinemediaobject"><img src="../images/error_no_regions.jpg"></span></p><p>This is neither very readable nor beautiful, clearly. And we do not even have
|
|
any action on the transitions yet.</p><p>Luckily, UML provides a helpful concept, orthogonal regions. See them as
|
|
lightweight state machines running at the same time in a same state machine and
|
|
having the capability to influence one another. The effect is that you have
|
|
several active states at any time. We can therefore keep our state machine from
|
|
the previous example and just define a new region made of two states, AllOk and
|
|
ErrorMode. AllOk is most of the time active. But the error_found error event
|
|
makes the second region move to the new active state ErrorMode. This event does
|
|
not interest the main region so it will simply be ignored.
|
|
"<code class="code">no_transition</code>" will be called only if no region at all handles
|
|
the event. </p><p>Adding an orthogonal region is easy, one only needs to declare more states in
|
|
the <code class="code">initial_state</code> typedef. So, adding a new region with AllOk as
|
|
the region's initial state is:</p><p><code class="code">typedef mpl::vector<Empty,AllOk> initial_state;</code></p><p><span class="inlinemediaobject"><img src="../images/Orthogonal-deferred.jpg"></span></p><p>Furthermore, when you detect an error, you usually do not want other events to
|
|
be handled. To achieve this, we use another UML feature, terminate states. When
|
|
any region moves to a terminate state, the state machine “terminates” (the state
|
|
machine and all its states stay alive) and all further events are ignored. This
|
|
is of course not mandatory, one can use orthogonal regions without terminate
|
|
states. Also note that, as UML mandates, every region gets a chance of handling
|
|
the event, in the order as declared by the <code class="code">initial_state</code> type. MSM
|
|
also provides a small extension to UML, interrupt states. If you declare
|
|
ErrorMode as interrupt state instead of terminate state, the state machine will
|
|
not handle any event other than the one which ends the interrupt. So it's like a
|
|
terminate state, with the difference that you are allowed to resume the state
|
|
machine when a condition (like handling of the original error) is met. </p><p>Last but not least, this example also shows here the handling of event
|
|
deferring. Let's say someone puts a disc and immediately presses play. The event
|
|
cannot be handled, yet you'd want it to be handled at a later point and not
|
|
force the user to press play again. The solution is to define it as deferred in
|
|
the Empty and Open states and get it handled in the first state where the event
|
|
is not to be deferred. It can then be handled or rejected. In this example, when
|
|
Stopped becomes active, the event will be handled because only Empty and Open
|
|
defer the event.</p><p>Notice how UML defines event deferring as a state property. To accomodate
|
|
this, MSM lets you specify this in states by providing a
|
|
<code class="code">deferred_events</code> type:</p><p><code class="code">struct Empty : public msm::front::state<> </code></p><p><code class="code">{ </code></p><p><code class="code">// if the play event is fired while in this state, defer it until a
|
|
state </code></p><p><code class="code">// handles or rejects it</code></p><p><code class="code"> typedef mpl::vector<play> deferred_events;</code></p><p><code class="code">...};</code></p><p>Please have a look at the <a class="link" href="examples/Orthogonal-deferred.cpp" target="_top">complete example</a>.</p><p>While this is wanted by UML and is simple, it is not always practical because
|
|
one could wish to defer only in certain conditions. One could also want to make
|
|
this be part of a transition action with the added bonus of a guard. It would
|
|
also be conform to the MSM philosophy to get as much as possible in the
|
|
transition table, where you can have all the important state machine structure
|
|
grouped together. This is also possible but not practical with this front-end so
|
|
we will need to pick a different row from the functor front-end. For a complete
|
|
description of the <code class="code">Row</code> type, please have a look at the <span class="command"><strong><a class="command" href="ar01s04.html#functor-front-end">functor front-end.</a></strong></span></p><p>First, as there is no state where MSM can detect the requirement of this
|
|
feature, we need to require deferred events capability explicitly, by adding a
|
|
type in the state machine definition:</p><p><code class="code">struct player_ : public
|
|
msm::front::state_machine_def<player_></code></p><p><code class="code">{ </code></p><p><code class="code">typedef int activate_deferred_events;</code></p><p><code class="code">...};</code></p><p>We can now defer an event in any transition of the transition table by using
|
|
as action the predefined <code class="code">msm::front::Defer</code> functor, for
|
|
example:</p><p><code class="code">Row < Empty , play , none , Defer , none ></code></p><p>This is an internal transition row(see <span class="command"><strong><a class="command" href="ar01s04.html#internal-transitions">internal transitions</a></strong></span>) but you
|
|
can ignore this for the moment. It just means that we are not leaving the Empty
|
|
state. What matters is that we use Defer as action. This is roughly equivalent
|
|
to the previous syntax but has the advantage of giving you all the information
|
|
in the transition table.</p><p>The second difference is that as we now have a transition defined, this
|
|
transition can play in the resolution of <span class="command"><strong><a class="command" href="ar01s03.html#transition-conflict">transition conflicts</a></strong></span>. For
|
|
example, we could model an "if (condition2) move to Playing else if (condition1)
|
|
defer play event":</p><p>
|
|
<code class="code">Row < Empty , play , none , Defer , condition1 >,</code></p><p><code class="code">g_row < Empty , play , Playing , &player_::condition2
|
|
></code></p><p>Please have a look at <a class="link" href="examples/Orthogonal-deferred2.cpp" target="_top">this possible implementation</a>.</p></div><div class="sect3" title="History"><div class="titlepage"><div><div><h4 class="title"><a name="d0e1361"></a>History</h4></div></div></div><p>UML defines two types of history, Shallow History and Deep History. What is it
|
|
and when do you need it? In the previous examples, if the player was playing the
|
|
second song and the user pressed pause, leaving Playing, at the next press on
|
|
the play button, the Playing state would become active and the first song would
|
|
play again. Soon would the first client complaints follow. They'd of course
|
|
demand, that if the player was paused, then it should remember which song was
|
|
playing. But it the player was stopped, then it should restart from the first
|
|
song. Now, how can it be done? Of course, you could add a bit of programming
|
|
logic and generate extra events to make the second song start if coming from
|
|
Pause. Something like: </p><p><code class="code">if (Event == end_pause) { for (int i=0;i< song number;++i) {
|
|
player.process_event(NextSong()); } } </code></p><p>Not much to like in this example, isn't it? To solve this problem, you define
|
|
what is called a shallow or a deep history. A shallow history reactivates the
|
|
last active state of a submachine when this state machine becomes active again.
|
|
The deep history does the same recursively, so if this last active state of the
|
|
submachine was itself a submachine, its last active state would become active
|
|
and this will continue until an active state is a normal state. For example, let
|
|
us have a look at the following UML diagram: </p><p><span class="inlinemediaobject"><img src="../images/HistoryTutorial.jpg"></span></p><p>Notice that the main difference compared to previous diagrams is that the
|
|
initial state is gone and replaced by a History symbol (the H inside a
|
|
circle).</p><p>As explained in the <span class="command"><strong><a class="command" href="ar01s03.html#uml-history">small UML
|
|
tutorial</a></strong></span>, History is a good concept with a not completely
|
|
satisfying specification. MSM kept the concept but not the specification. Msm
|
|
goes another way and makes this a policy so you can define your own history
|
|
types. Furthermore, History is a backend policy. This allows you to reuse the
|
|
same state machine frontend with different history policies.</p><p>Concretely, your frontend stays unchanged:</p><p><code class="code">struct Playing_ : public
|
|
msm::front::state_machine_def<Playing_></code></p><p>You then add the policy to the backend:</p><p><code class="code">typedef
|
|
msm::back::state_machine<Playing_,msm::back::ShallowHistory<mpl::vector<end_pause>
|
|
> > Playing;</code></p><p>This states that a shallow history must be activated if the Playing state
|
|
machine gets activated by the end_pause event and only this one (or any other
|
|
event added to the mpl::vector). If the state machine was in the Stopped state
|
|
and the event play was generated, the history would not be activated and the
|
|
normal initial state would become active. By default, history is disabled. For
|
|
your convenience the library provides in addition to ShallowHistory a non-UML
|
|
standard AlwaysHistory policy (likely to be your main choice) which always
|
|
activates history, whatever event triggers the submachine activation. Deep
|
|
history is not directly available. The reason is that it would conflict with
|
|
policies which submachines could define. Of course, if for example, Song1 were a
|
|
state machine itself, it could use the ShallowHistory policy itself thus
|
|
creating Deep History. </p></div><div class="sect3" title="Anonymous transitions"><div class="titlepage"><div><div><h4 class="title"><a name="d0e1394"></a>Anonymous transitions</h4></div></div></div><p><span class="command"><strong><a name="anonymous-transitions"></a></strong></span>The following diagram shows an
|
|
example making use of this feature:</p><p><span class="inlinemediaobject"><img src="../images/Anonymous.jpg"></span></p><p>Anonymous transitions are transitions without a named event. This means that
|
|
the transition automatically fires when the predecessor state is entered (to be
|
|
exact, after the entry action). Otherwise it is a normal transition with actions
|
|
and guards. Why would you need something like that? A possible case would be if
|
|
a part of your state machine implements some algorithm, where states are steps
|
|
of the algorithm implementation. Then, using several anonymous transitions with
|
|
different guard conditions, you are actually implementing some if/else
|
|
statement. Another possible use would be a real-time system called at regular
|
|
intervals and always doing the same thing, meaning implementing the same
|
|
algorithm. The advantage is that once you know how long a transition takes to
|
|
execute on the system, by calculating the longest path (the number of
|
|
transitions from start to end), you can pretty much know how long your algorithm
|
|
will take in the worst case, which in turns tells you how big of a time frame
|
|
you are to request from a scheduler. </p><p>If you are using Executable UML (a good book describing it is "Executable UML,
|
|
a foundation for Model-Driven Architecture"), you will notice that it is common
|
|
for a state machine to generate an event to itself only to leave a state.
|
|
Anonymous transitions free you from this constraint.</p><p>If you do not use this feature in a concrete state machine, MSM will
|
|
deactivate it and you will not pay for it. If you use it, there is however a
|
|
small performance penalty as MSM will try to fire a compound event (the other
|
|
UML name for anonymous transitions) after every taken transition. This will
|
|
therefore double the event processing cost, which is not as bad as it sounds as
|
|
MSM’s execution speed is very high anyway.</p><p>To define such a transition, use “none” as event in the transition table, for
|
|
example:</p><p><code class="code">row < State3 , none , State4 , &p::State3ToState4 ,
|
|
&p::always_true ></code></p><p><a class="link" href="examples/AnonymousTutorial.cpp" target="_top">An implementation</a> of
|
|
the state machine diagram is also provided.</p></div><div class="sect3" title="Internal transitions"><div class="titlepage"><div><div><h4 class="title"><a name="d0e1419"></a><span class="command"><strong><a name="internal-transitions"></a></strong></span>Internal transitions</h4></div></div></div><p>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. This is
|
|
useful when all you want is to execute some code for a given event in a given
|
|
state.</p><p>Internal transitions are specified as having a higher priority than normal
|
|
transitions. While it makes sense for a submachine with exit points, it is
|
|
surprising for a simple state. MSM lets you define the transition priority by
|
|
setting the transition’s position inside the transition table (see <span class="command"><strong><a class="command" href="ar01s07.html#run-to-completion">internals</a></strong></span> ). The difference
|
|
between "normal" and internal transitions is that internal transitions have no
|
|
target state, therefore we need new row types. We had a_row, g_row, _row and
|
|
row, we now add a_irow, g_irow, _irow and irow which are like normal transitions
|
|
but define no target state. For, example an internal transition with a guard
|
|
condition could be:</p><p><code class="code">g_irow < Empty /*state*/ , cd_detected
|
|
/*event*/,&p::internal_guard /* guard */ ></code></p><p>These new row types can be placed anywhere in the transition table so that you
|
|
can still have your state machine structure grouped together. The only
|
|
difference of behavior with the UML standard is the missing notion of priority.
|
|
Please have a look at <a class="link" href="examples/SimpleTutorialInternal.cpp" target="_top">the
|
|
example</a>.</p><p>It is also possible to do it the UML-conform way by declaring a transition
|
|
table called <code class="code">internal transition_table</code> inside the state itself and
|
|
using internal row types. For example:</p><p><code class="code">struct Empty : public msm::front::state<> {</code></p><p><code class="code">struct internal_transition_table : mpl::vector<</code></p><p><code class="code">a_internal < cd_detected , Empty, &Empty::internal_action
|
|
></code></p><p><code class="code">> {};</code></p><p><code class="code">};</code></p><p>This declares an internal transition table called internal_transition_table
|
|
and reacting on the event cd_detected by calling internal_action on Empty. Let
|
|
us note a few points:</p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>internal tables are NOT called transition_table but
|
|
internal_transition_table</p></li><li class="listitem"><p>they use different but similar row types: a_internal, g_internal,
|
|
_internal and internal.</p></li><li class="listitem"><p>These types take as first template argument the triggering event
|
|
and then the action and guard method. Note that the only real
|
|
difference to classical rows is the extra argument before the
|
|
function pointer. This is the type on which the function will be
|
|
called.</p></li><li class="listitem"><p>This also allows you, if you wish, to define actions and guards in
|
|
another state of the state machine or in the state machine
|
|
itself.</p></li><li class="listitem"><p>submachines can have an internal transition table and a classical
|
|
transition table.</p></li></ul></div><p>The <a class="link" href="examples/TestInternal.cpp" target="_top">following example</a>
|
|
makes use of an a_internal. It also uses functor-based internal transitions
|
|
which will be explained in <span class="command"><strong><a class="command" href="ar01s04.html#functor-internal-transitions">the functor front-end</a></strong></span>, please ignore them for the moment. Also
|
|
note that the state-defined internal transitions, having following the UML
|
|
standard the highest priority, are tried before those defined inside the state
|
|
machine transition table.</p><p>Which method should you use? It depends on what you need:</p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>the first version (using irow) is simpler and likely to compile
|
|
faster. It also lets you choose the priority of your internal
|
|
transition.</p></li><li class="listitem"><p>the second version is more logical from a UML perspective and lets
|
|
you make states more useful and reusable. It also allows you to call
|
|
actions and guards on any state of the state machine</p></li></ul></div><p>
|
|
<span class="command"><strong><a name="internal-transitions-note"></a></strong></span><span class="underline"><span class="bold"><strong>Note</strong></span></span>: There is an added
|
|
possibility coming from this feature. The <code class="code">internal_transition_table</code>
|
|
transitions being added directly inside the main state machine's transition
|
|
table, it is possible, if it is more to your state, to distribute your state
|
|
machine definition a bit like Boost.Statechart, leaving the state machine itself
|
|
the only task of declaring the states it wants to use using the
|
|
<code class="code">explicit_creation</code> type definition. While this is not the
|
|
author's favorite way, it is still possible. A simplified example using only two
|
|
states will make it clearer:</p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p><a class="link" href="examples/distributed_table/DistributedTable.cpp" target="_top">state machine definition</a></p></li><li class="listitem"><p>Empty <a class="link" href="examples/distributed_table/Empty.hpp" target="_top">header</a> and <a class="link" href="examples/distributed_table/Empty.cpp" target="_top">cpp</a></p></li><li class="listitem"><p>Open <a class="link" href="examples/distributed_table/Open.hpp" target="_top">header</a> and <a class="link" href="examples/distributed_table/Open.cpp" target="_top">cpp</a></p></li><li class="listitem"><p><a class="link" href="examples/distributed_table/Events.hpp" target="_top">events
|
|
definition</a></p></li></ul></div><p>There is an added bonus offered for submachines, which can have both the
|
|
standard transition_table and an internal_transition_table (which has higher
|
|
priority). This makes it easier if you decide to make a full submachine from a
|
|
state. It is also slightly faster than the standard alternative, adding
|
|
orthogonal regions, because event dispatching will, if accepted by the internal
|
|
table, not continue to the subregions. This gives you a O(1) dispatch instead of
|
|
O(number of regions). While the example is with eUML, the same is also possible
|
|
with this front-end.</p></div><div class="sect3" title="more row types"><div class="titlepage"><div><div><h4 class="title"><a name="d0e1532"></a>more row types</h4></div></div></div><p>It is also possible to write transitions using actions and guard conditions
|
|
not just from the state machine but also from its contained states. In this
|
|
case, one must specify not just a method pointer but also the object on which to
|
|
call it. This transition row is called, not very originally, <code class="code">row2</code>.
|
|
They come, like normal transitions in four flavors: <code class="code">a_row2, g_row2, _row2
|
|
and row2</code>. For example, a transition calling an action from the state
|
|
Empty could be:</p><p><code class="code">a_row2 < Stopped , open_close , Open , Empty /*action source*/ ,
|
|
&Empty::open_drawer /*action*/></code></p><p>The same capabilities are also available for internal transitions so that we
|
|
have: <code class="code">a_irow2, g_irow2, _irow2 and row2</code>. For transitions defined as
|
|
part of the <code class="code">internal_transition_table</code>, you can use the <span class="command"><strong><a class="command" href="ar01s04.html#internal-transitions">a_internal, g_internal, _internal,
|
|
internal</a></strong></span> row types.</p><p>These row types allow us to distribute the state machine code among states,
|
|
making them reusable and more valuable. Using transition tables inside states
|
|
also contributes to this possibility. An <a class="link" href="examples/SimpleTutorial2.cpp" target="_top">example</a> of these new tows
|
|
is also provided.</p></div><div class="sect3" title="Explicit entry / entry and exit pseudo-state / fork"><div class="titlepage"><div><div><h4 class="title"><a name="d0e1562"></a>Explicit entry / entry and exit pseudo-state / fork</h4></div></div></div><p>MSM (almost) fully supports these features described in the <span class="command"><strong><a class="command" href="ar01s03.html#uml-history">small UML tutorial</a></strong></span>. Almost because there
|
|
are currently two limitations: </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>it is only possible to explicitly enter a sub- state of the target
|
|
but not a sub-sub state.</p></li><li class="listitem"><p>it is not possible to explicitly exit. Exit points must be
|
|
used.</p></li></ul></div><p>Let us see a concrete example:</p><p><span class="inlinemediaobject"><img src="../images/entry%20tutorial.jpg"></span></p><p>We find in this diagram:</p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>A “normal” entering into SubFsm2 triggered by event1 and back to
|
|
State1 using the same event. In each zone is the initial state
|
|
activated, i.e. SubState1 and SubState1b.</p></li><li class="listitem"><p>An explicit entry into SubFsm2::SubState2 for zone “a” with event2
|
|
as trigger, meaning that in region “b” the initial state,
|
|
SubState1b, activated.</p></li><li class="listitem"><p>A fork into zones “a” and “b” to the explicit entries SubState2
|
|
and SubState2b, triggered by event3. Both states become active so no
|
|
zone is default activated (if we had a third zone, it would
|
|
be).</p></li><li class="listitem"><p>A connection of two transitions through an entry pseudo state,
|
|
SubFsm2::PseudoEntry1, triggered by event4 and triggering also the
|
|
second transition on the same event (both transitions must be
|
|
triggered by the same event). Zone “b” gets default-activated and
|
|
SubState1b becomes active.</p></li><li class="listitem"><p>An exit from SubFsm2 using an exit pseudo-state, PseudoExit1,
|
|
triggered by event5 and connecting two transitions using the same
|
|
event. Again, the event is forwarded to the second transition and
|
|
both regions are exited, as SubFsm2 becomes inactive. Note that if
|
|
no transition is defined from PseudoExit1, an error (as defined in
|
|
the UML standard) will be detected and no_transition called.</p></li></ul></div><p>The example is also <a class="link" href="examples/DirectEntryTutorial.cpp" target="_top">fully
|
|
implemented</a>.</p><p>This sounds complicated but the syntax is simple.</p><div class="sect4" title="Explicit entry"><div class="titlepage"><div><div><h5 class="title"><a name="d0e1608"></a>Explicit entry</h5></div></div></div><p>First, to define that a state is an explicit entry, you have to make it a
|
|
state and mark it as explicit, giving as template parameters the zone id
|
|
(the zone id starts with 0 and corresponds to the first initial state of the
|
|
initial_state type sequence).</p><p><code class="code">struct SubState2 : public msm::front::state<> , public
|
|
msm::front::explicit_entry<0></code></p><p>And define the submachine as:</p><p><code class="code">typedef msm::back::state_machine<SubFsm2_> SubFsm2;</code></p><p>You can then use it as target in a transition with State1 as
|
|
source:</p><p><code class="code">_row < State1, Event2, SubFsm2::direct< SubFsm2_::SubState2>
|
|
></code></p><p>The syntax deserves some explanation. SubFsm2_ is a front end. SubState2
|
|
is a nested state, therefore the SubFsm2_::SubState2 syntax. The containing
|
|
machine (containing State1 and SubFsm2) refers to the backend instance
|
|
(SubFsm2). SubFsm2::direct states that a direct entry is desired.</p><p><span class="underline">Note (also valid for forks)</span>: in
|
|
order to make compile time more bearable for the more standard cases, and
|
|
unlike initial states, explicit entry states which are also not found in the
|
|
transition table of the entered submachine (a rare case) do NOT get
|
|
automatically created. To explicitly create such states, you need to add in
|
|
the state machine containing the explicit states a simple typedef giving a
|
|
sequence of states to be explicitly created like:</p><p><code class="code">typedef mpl::vector<SubState2,SubState2b>
|
|
explicit_creation;</code></p></div><div class="sect4" title="Fork"><div class="titlepage"><div><div><h5 class="title"><a name="d0e1635"></a>Fork</h5></div></div></div><p>Need a fork instead of an explicit entry? Then, as a fork is an explicit
|
|
entry into states of different regions, we do not change the state
|
|
definition compared to the explicit entry and specify as target a list of
|
|
explicit entry states:</p><p><code class="code">_row < State1, Event3, mpl::vector<SubFsm2::direct<
|
|
SubFsm2_::SubState2>, SubFsm2::direct <SubFsm2_::SubState2b>
|
|
></code></p><p>With SubState2 defined as before and SubState2b defined as being in the
|
|
second region (Caution: MSM does not check that the region is
|
|
correct):</p><p><code class="code">struct SubState2b : public msm::front::state<> , public
|
|
msm::front::explicit_entry<1></code></p></div><div class="sect4" title="Entry pseudo states"><div class="titlepage"><div><div><h5 class="title"><a name="d0e1648"></a>Entry pseudo states</h5></div></div></div><p> To define an entry pseudo state, you need derive from the corresponding
|
|
class and give the region id:</p><p><code class="code">struct PseudoEntry1 : public
|
|
msm::front::entry_pseudo_state<0></code></p><p>And add the corresponding transition in Fsm's transition table:</p><p><code class="code">_row < State1, Event4,
|
|
SubFsm2::entry_pt<SubFsm2_::PseudoEntry1> ></code></p><p>And another in the SubFsm2_ submachine definition (remember that UML
|
|
defines an entry point as a connection between two transitions), for example
|
|
this time with an action method:</p><p><code class="code">_row < PseudoEntry1, Event4, SubState3,
|
|
&SubFsm2_::entry_action ></code></p></div><div class="sect4" title="Exit pseudo states"><div class="titlepage"><div><div><h5 class="title"><a name="d0e1666"></a> Exit pseudo states </h5></div></div></div><p>And finally, exit pseudo states are to be used almost the same way, but
|
|
defined differently: it takes as template argument the event to be forwarded
|
|
(no region id is necessary):</p><p><code class="code">struct PseudoExit1 : public
|
|
exit_pseudo_state<event6></code></p><p>And you need, as for entry pseudo states, two transitions, one in the
|
|
submachine:</p><p><code class="code">_row < SubState3, Event5, PseudoExit1 ></code></p><p>And one in the containing state machine:</p><p><code class="code">_row < SubFsm2::exit_pt<SubFsm2_::PseudoExit1>, Event6, State2
|
|
></code></p><p><span class="underline">Important note 1:</span> UML defines
|
|
transiting to an entry pseudo state and having either no second transition
|
|
or one with a guard as an error but defines no error handling. MSM will
|
|
tolerate this behavior; the entry pseudo state will simply be the newly
|
|
active state.</p><p><span class="underline">Important note 2</span>: UML defines
|
|
transiting to an exit pseudo state and having no second transition as an
|
|
error, and also defines no error handling. Therefore, it was decided to
|
|
implement exit pseudo state as terminate states and the containing composite
|
|
not properly exited will stay terminated as it was technically
|
|
“exited”.</p><p><span class="underline">Important note 3:</span> UML states that
|
|
for the exit point, the same event must be used in both transitions. MSM
|
|
relaxes this rule and only wants the event on the inside transition to be
|
|
convertible to the one of the outside transition. In our case, event6 is
|
|
convertible from event5. Notice that the forwarded event must be named in
|
|
the exit point definition. For example, we could define event6 as simply
|
|
as:</p><p><code class="code">struct event6 { event6(){} template <class Event> event6(Event
|
|
const&){} };//convertible from any event</code>
|
|
</p></div></div><div class="sect3" title="Flags"><div class="titlepage"><div><div><h4 class="title"><a name="d0e1700"></a>Flags</h4></div></div></div><p>This <a class="link" href="examples/Flags.cpp" target="_top">tutorial</a> is devoted to a
|
|
concept not defined in UML: flags. It has been added into MSM after proving
|
|
itself useful on many occasions. Please, do not be frightened as we are not
|
|
talking about ugly shortcuts made of an improbable collusion of Booleans.</p><p>If you look into the Boost.Statechart documentation you'll find some code
|
|
like:</p><p><code class="code">if ( ( state_downcast< const NumLockOff * >() != 0 ) &&
|
|
</code></p><p><code class="code">( state_downcast< const CapsLockOff * >() != 0 ) &&
|
|
</code></p><p><code class="code">( state_downcast< const ScrollLockOff * >() != 0 ) ) </code></p><p>While correct and found in many UML books, this can be error-prone and a
|
|
potential time-bomb when your state machine grows and you add new states or
|
|
orthogonal regions.</p><p>And most of all, it hides the real question, which would be “does my state
|
|
machine's current state define a special property”? In this special case “are my
|
|
keys in a lock state”? So let's apply the Fundamental Theorem of Software
|
|
Engineering and move one level of abstraction higher.</p><p>In our player example, let's say we need to know if the player has a loaded
|
|
CD. We could do the same:</p><p><code class="code">if ( ( state_downcast< const Stopped * >() != 0 ) &&
|
|
</code></p><p><code class="code">( state_downcast< const Open * >() != 0 ) && </code></p><p><code class="code">( state_downcast< const Paused * >() != 0 ) &&</code></p><p><code class="code">( state_downcast< const Playing * >() != 0 )</code></p><p><code class="code"> ) </code></p><p>Or flag these 4 states as CDLoaded-able. You add a flag_list type into each
|
|
flagged state:</p><p><code class="code">typedef mpl::vector1<CDLoaded> flag_list;</code></p><p>You can even define a list of flags, for example in Playing:</p><p><code class="code">typedef mpl::vector2<PlayingPaused,CDLoaded> flag_list;</code></p><p>This means that Playing supports both properties. Now to check if your player
|
|
has a loaded CD, check if your flag is active in the current state:</p><p><code class="code">player p; if (p.is_flag_active<CDLoaded>()) ... </code></p><p>And what if you have orthogonal regions? How to decide if a state machine is
|
|
in a flagged state? By default, you keep the same code and the current states
|
|
will be OR'ed, meaning if one of the active states has the flag, then
|
|
is_flag_active returns true. Of course, in some cases, you might want that all
|
|
of the active states are flagged for the state to be active. You can also AND
|
|
the active states:</p><p><code class="code">if (p.is_flag_active<CDLoaded,player::Flag_AND>()) ...</code></p><p>The following diagram displays the flag situation in the tutorial.</p><p><span class="inlinemediaobject"><img src="../images/FlagsTutorial.jpg"></span></p></div><div class="sect3" title="Event Hierarchy"><div class="titlepage"><div><div><h4 class="title"><a name="d0e1766"></a>Event Hierarchy</h4></div></div></div><p>There are cases where transitions with many related but different events are
|
|
needed. An example is text parsing. Let's say you want to parse a string and use
|
|
a state machine to handle you parsing state. You want to parse 4 digits and
|
|
decide to use a state for every matched digit. Your state machine could look
|
|
like:</p><p><span class="inlinemediaobject"><img src="../images/ParsingDigits.jpg"></span></p><p>But how to detect the digit event? We would like to avoid having to define 10
|
|
transitions on char_0, char_1... between two states as it would force us to
|
|
write 4 x 10 transitions and the compile-time would suffer. To solve this
|
|
problem, MSM supports the triggering of a transition on a subclass event. For
|
|
example, if we define digits as: </p><p><code class="code">struct digit {};</code></p><p><code class="code">struct char_0 : public digit {}; </code></p><p>And to the same for other digits, we can now fire char_0, char_1 events and
|
|
this will cause a transition with "digit" as trigger to be taken.</p><p>An example with performance measurement, taken from the documentation of
|
|
Boost.Xpressive illustrates this example (TODO). You might notice that the
|
|
performance is actually very good (better).</p></div><div class="sect3" title="Containing state machine (deprecated)"><div class="titlepage"><div><div><h4 class="title"><a name="d0e1787"></a> Containing state machine (deprecated)</h4></div></div></div><p>This feature is still supported in MSM for backward compatibility but made
|
|
obsolete by the fact that every guard/action/entry action/exit action get the
|
|
state machine passed as argument and might be removed at a later time.</p><p>All of the states defined in the state machine are created upon state machine
|
|
construction. This has the huge advantage of a reduced syntactic noise. The cost
|
|
is a small loss of control of the user on the state creation and access. But
|
|
sometimes you needed a way for a state to get access to its containing state
|
|
machine. Basically, a state needs to change its declaration to:</p><p><code class="code">struct Stopped : public msm::front::state<sm_ptr></code></p><p>And to provide a set_sm_ptr function: <code class="code">void set_sm_ptr(player*
|
|
pl)</code></p><p>to get a pointer to the containing state machine. The same applies to
|
|
terminate_state / interrupt_state and entry_pseudo_state / exit_pseudo_state.
|
|
</p></div></div><div class="sect2" title="Functor front-end"><div class="titlepage"><div><div><h3 class="title"><a name="d0e1803"></a><span class="command"><strong><a name="functor-front-end"></a></strong></span>Functor front-end</h3></div></div></div><p>The functor front-end is the preferred front-end at the moment. It is more
|
|
powerful than the standard front-end, slightly faster and has a more readable
|
|
transition table. It also makes it easier to reuse parts of state machines. Like
|
|
<span class="command"><strong><a class="command" href="ar01s04.html#eUML-front-end">eUML</a></strong></span>, il also comes with a good
|
|
deal of predefined actions. Actually, eUML generates a functor front-end through
|
|
Boost.Typeof and Boost.Proto so both offer the same functionality.</p><p>The rows which MSM offers come in different flavors. We saw the a_row, g_row,
|
|
_row, row, not counting internal rows. This is already much to know, so why define
|
|
new rows? These types have some disadvantages: </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>They are more typing and information than we would wish. This means
|
|
syntactic noise.</p></li><li class="listitem"><p>Function pointers are weird in C++.</p></li><li class="listitem"><p>The action/guard signature is limited and does not allow for more
|
|
variations of parameters (source state, target state, current state
|
|
machine, etc.)</p></li><li class="listitem"><p>It is not easy to reuse action code from a state machine to
|
|
another.</p></li></ul></div><div class="sect3" title="Transition table"><div class="titlepage"><div><div><h4 class="title"><a name="d0e1827"></a> Transition table </h4></div></div></div><p>We can change the definition of the simple tutorial's transition table
|
|
to:</p><p>
|
|
</p><table id="d0e1834"><tbody><tr>
|
|
<td>//</td>
|
|
<td>Start</td>
|
|
<td>Event</td>
|
|
<td>Next</td>
|
|
<td>Action</td>
|
|
<td>Guard</td>
|
|
<td> </td>
|
|
</tr><tr>
|
|
<td>//</td>
|
|
<td>+---------+</td>
|
|
<td>-------------+</td>
|
|
<td>---------+</td>
|
|
<td>---------------------+</td>
|
|
<td>----------------------+</td>
|
|
<td> </td>
|
|
</tr><tr>
|
|
<td>Row <</td>
|
|
<td>Stopped ,</td>
|
|
<td>play,</td>
|
|
<td>Playing,</td>
|
|
<td>start_playback</td>
|
|
<td> </td>
|
|
<td>>,</td>
|
|
</tr><tr>
|
|
<td>Row <</td>
|
|
<td>Stopped ,</td>
|
|
<td>open_close,</td>
|
|
<td>Open,</td>
|
|
<td>open_drawer,</td>
|
|
<td> none</td>
|
|
<td>>,</td>
|
|
</tr><tr>
|
|
<td>Row <</td>
|
|
<td>Stopped ,</td>
|
|
<td>stop,</td>
|
|
<td>Stopped,</td>
|
|
<td> </td>
|
|
<td> none</td>
|
|
<td>>,</td>
|
|
</tr><tr>
|
|
<td>//</td>
|
|
<td>+---------</td>
|
|
<td>-------------+</td>
|
|
<td>---------+</td>
|
|
<td>---------------------+</td>
|
|
<td>----------------------+</td>
|
|
<td> </td>
|
|
</tr><tr>
|
|
<td>Row <</td>
|
|
<td>Open ,</td>
|
|
<td>open_close ,</td>
|
|
<td>Empty ,</td>
|
|
<td>close_drawer,</td>
|
|
<td> none</td>
|
|
<td>>,</td>
|
|
</tr><tr>
|
|
<td>//</td>
|
|
<td>+---------+</td>
|
|
<td>-------------+</td>
|
|
<td>---------+</td>
|
|
<td>---------------------+</td>
|
|
<td>----------------------+</td>
|
|
<td> </td>
|
|
</tr><tr>
|
|
<td>Row <</td>
|
|
<td>Empty ,</td>
|
|
<td>open_close ,</td>
|
|
<td>Open ,</td>
|
|
<td>open_drawer</td>
|
|
<td> </td>
|
|
<td>>,</td>
|
|
</tr><tr>
|
|
<td>Row <</td>
|
|
<td>Empty ,</td>
|
|
<td>cd_detected ,</td>
|
|
<td>Stopped ,</td>
|
|
<td>store_cd_info ,</td>
|
|
<td>good_disk_format</td>
|
|
<td>>,</td>
|
|
</tr><tr>
|
|
<td>g_row <</td>
|
|
<td>Empty ,</td>
|
|
<td>cd_detected ,</td>
|
|
<td>Playing ,</td>
|
|
<td>store_cd_info ,</td>
|
|
<td>&player_::auto_start</td>
|
|
<td>>,</td>
|
|
</tr><tr>
|
|
<td>//</td>
|
|
<td>+---------+</td>
|
|
<td>-------------+</td>
|
|
<td>---------+</td>
|
|
<td>---------------------+</td>
|
|
<td>----------------------+</td>
|
|
<td> </td>
|
|
</tr><tr>
|
|
<td>Row <</td>
|
|
<td>Playing ,</td>
|
|
<td>stop ,</td>
|
|
<td>Stopped ,</td>
|
|
<td>stop_playback,</td>
|
|
<td> none</td>
|
|
<td>>,</td>
|
|
</tr><tr>
|
|
<td>Row <</td>
|
|
<td>Playing ,</td>
|
|
<td>pause ,</td>
|
|
<td>Paused ,</td>
|
|
<td>pause_playback,</td>
|
|
<td> none</td>
|
|
<td>>,</td>
|
|
</tr><tr>
|
|
<td>Row <</td>
|
|
<td>Playing ,</td>
|
|
<td>open_close ,</td>
|
|
<td>Open ,</td>
|
|
<td>stop_and_open,</td>
|
|
<td> none</td>
|
|
<td>>,</td>
|
|
</tr><tr>
|
|
<td>//</td>
|
|
<td>+---------+</td>
|
|
<td>-------------+</td>
|
|
<td>---------+</td>
|
|
<td>---------------------+</td>
|
|
<td>----------------------+</td>
|
|
<td> </td>
|
|
</tr><tr>
|
|
<td>Row <</td>
|
|
<td> Paused ,</td>
|
|
<td>end_pause ,</td>
|
|
<td>Playing ,</td>
|
|
<td>resume_playback,</td>
|
|
<td> none</td>
|
|
<td>>,</td>
|
|
</tr><tr>
|
|
<td>Row <</td>
|
|
<td> Paused ,</td>
|
|
<td>stop ,</td>
|
|
<td>Stopped ,</td>
|
|
<td>stop_playback,</td>
|
|
<td> none</td>
|
|
<td>>,</td>
|
|
</tr><tr>
|
|
<td>Row <</td>
|
|
<td> Paused ,</td>
|
|
<td>open_close ,</td>
|
|
<td>Open ,</td>
|
|
<td>stop_and_open,</td>
|
|
<td> none</td>
|
|
<td>></td>
|
|
</tr><tr>
|
|
<td>//</td>
|
|
<td>+---------+</td>
|
|
<td>-------------+</td>
|
|
<td>---------+</td>
|
|
<td>---------------------+</td>
|
|
<td>----------------------+</td>
|
|
<td> </td>
|
|
</tr><tr>
|
|
<td>> {};</td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
</tr></tbody></table><p>
|
|
</p><p>Transitions are now of type "Row" with exactly 5 template arguments: source
|
|
state, event, target state, action and guard. Wherever there is nothing (for
|
|
example actions and guards), write "none". Actions and guards are no more
|
|
methods but functors getting as arguments the detected event, the state machine,
|
|
source and target state:</p><p><code class="code">struct store_cd_info { </code></p><p><code class="code">template <class Fsm,class Evt,class SourceState,class TargetState>
|
|
</code></p><p><code class="code">void operator()(Evt const&, Fsm& fsm, SourceState&,
|
|
TargetState& ) </code></p><p><code class="code"> {</code></p><p><code class="code"> cout << "player::store_cd_info" << endl;
|
|
fsm.process_event(play()); </code></p><p><code class="code"> } </code></p><p><code class="code">}; </code></p><p>The advantage to functors compared to functions are that they are generic and
|
|
reusable. They also allow passing more parameters than just events. The guard
|
|
functors are the same but have an operator() returning a bool.</p><p>It is also possible to mix rows from different front-ends. To show this, a
|
|
g_row has been left in the transition table. <span class="underline">Note:</span> in case the action functor is used in the transition table
|
|
of a state machine contained inside a top-level state machine, the “fsm”
|
|
parameter refers to the lowest-level state machine (referencing this action),
|
|
not the top-level one.</p><p>To illustrate the reusable point, MSM comes with a whole set of predefined
|
|
functors. Please refer to eUML for the full list (TODO). For example, we are
|
|
going to replace the first action by an action sequence and the guard by a more
|
|
complex functor.</p><p>We decide we now want to execute 2 actions in the first transition (Stopped ->
|
|
Playing). We only need to change the action start_playback to (TODO)
|
|
<code class="code">ActionSequence_< mpl::vector<some_action, start_playback> >
|
|
</code> and now will execute some_action and start_playback every time the
|
|
transition is taken. ActionSequence_ is a functor callinng each element of the
|
|
mpl::vector in sequence.</p><p>We also want to replace good_disk_format by a condition of the type:
|
|
“good_disk_format && (some_condition || some_other_condition)”. We can
|
|
achieve this using And_ and Or_ functors: <code class="code">And_<good_disk_format,Or_<
|
|
some_condition , some_other_condition></code>. It even starts looking like
|
|
functional programming. MSM ships with functors for operators, state machine
|
|
usage, STL algorithms or container methods.</p></div><div class="sect3" title="Defining states with entry/exit actions"><div class="titlepage"><div><div><h4 class="title"><a name="d0e2362"></a>Defining states with entry/exit actions</h4></div></div></div><p>You probably noticed that we just showed a different transition table and that
|
|
we even mixed rows from different front-ends. This means that you can do this
|
|
and leave the definitions for states unchanged. Most examples are doing this as
|
|
it is the simplest solution. You still enjoy the simplicity of the first
|
|
front-end with the extended power of the new transition types. This <a class="link" href="examples/SimpleWithFunctors.cpp" target="_top">tutorial</a>, adapted from
|
|
the earlier example does just this.</p><p>Of course, it is also possible to define states where entry and exit actions
|
|
are also provided as functors as these are generated by eUML and both front-ends
|
|
are equivalent. For example, we can define a state as:</p><p><code class="code">struct Empty_Entry { </code></p><p><code class="code">template <class Event,class Fsm,class State> </code></p><p><code class="code">void operator()(Event const&,Fsm&,State&) </code></p><p><code class="code"> {</code></p><p><code class="code"> ... </code></p><p><code class="code"> } </code></p><p><code class="code">}; // same for Empty_Exit</code></p><p><code class="code">struct Empty : public
|
|
msm::front::euml::func_state<Empty_Entry,Empty_Exit>{};</code></p><p>This also means that you can, like in the transition table, write entry / exit
|
|
actions made of more complicated action combinations. The previous example can
|
|
therefore <a class="link" href="examples/SimpleWithFunctors2.cpp" target="_top">be
|
|
rewritten</a>.</p><p>Usually, however, one will probably use the standard state definition as it
|
|
provides the same capabilities as this front-end state definition, unless one
|
|
needs some of the shipped predefined functors.</p></div><div class="sect3" title="Defining a simple state machine"><div class="titlepage"><div><div><h4 class="title"><a name="d0e2403"></a>Defining a simple state machine</h4></div></div></div><p>Like states, state machines can be defined using the previous front-end, as
|
|
the previous example showed, or with the functor front-end, which allows you to
|
|
define a state machine entry and exit functions as functors, as in <a class="link" href="examples/SimpleWithFunctors2.cpp" target="_top">this example</a>.</p></div><div class="sect3" title="Anonymous transitions"><div class="titlepage"><div><div><h4 class="title"><a name="d0e2411"></a>Anonymous transitions</h4></div></div></div><p>Anonymous (compound) transitions are transition withour a named event, taken
|
|
automatically. We saw how this front-end uses <code class="code">none</code> when no action
|
|
or guard is required. We can also use <code class="code">none</code> instead of an event to
|
|
mark an anonymous transition. For example, the following transition makes an
|
|
immediate transition from State1 to State2:</p><p>Row < State1 , none , State2 ></p><p>The following transition does the same but calling an action in the
|
|
process:</p><p>Row < State1 , none , State2 , State1ToState2, none ></p><p>The following diagram shows an example and its <a class="link" href="examples/AnonymousTutorialWithFunctors.cpp" target="_top">implementation</a>:</p><p><span class="inlinemediaobject"><img src="../images/Anonymous.jpg"></span></p></div><div class="sect3" title="Internal transitions"><div class="titlepage"><div><div><h4 class="title"><a name="d0e2437"></a><span class="command"><strong><a name="functor-internal-transitions"></a></strong></span>Internal transitions</h4></div></div></div><p>The <a class="link" href="examples/SimpleTutorialInternalFunctors.cpp" target="_top">following
|
|
example</a> uses internal transitions with the functor front-end. As for
|
|
the simple standard front-end, both methods of defining internal transitions are supported:</p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>defining a <code class="code">Row</code> in the state machine's transition
|
|
table with <code class="code">none</code> as target state defines an internal
|
|
transition</p></li><li class="listitem"><p>defining an <code class="code">internal_transition_table</code> made of
|
|
<code class="code">Internal</code> rows inside a state defines UML-conform
|
|
internal transitions with higher priority</p></li><li class="listitem"><p>transitions defined inside <code class="code">internal_transition_table</code>
|
|
require no source state either as the source state is known.</p></li></ul></div><p>Like for the <span class="command"><strong><a class="command" href="ar01s04.html#internal-transitions-note">standard front-end internal transitions</a></strong></span>, internal transition
|
|
tables are added into the main state machine's table, thus allowing you to
|
|
distribute the transition table definition and reuse states.</p><p>There is an added bonus offered for submachines, which can have both the
|
|
standard transition_table and an internal_transition_table (which has higher
|
|
priority). This makes it easier if you decide to make a full submachine from a
|
|
state. It is also slightly faster than the standard alternative, adding
|
|
orthogonal regions, because event dispatching will, if accepted by the internal
|
|
table, not continue to the subregions. This gives you a O(1) dispatch instead of
|
|
O(number of regions). While the example is with eUML, the same is also possible
|
|
with this front-end.</p></div></div><div class="sect2" title="eUML (experimental)"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2477"></a><span class="command"><strong><a name="eUML-front-end"></a></strong></span>eUML (experimental)</h3></div></div></div><p><span class="underline">Important note</span>: eUML requires a compiler
|
|
supporting the C++0x decltype/typeof feature (from example VC >= 9, g++ >= 4.3. VC8
|
|
is partially supported). More generally, eUML has experimental status because most
|
|
compilers will start crashing when a state machine becomes too big. Only g++ 4.3
|
|
(unfortunately not 4.4 which shows a serious regression) seems perfectly
|
|
resilient.</p><p>The previous front-ends are simple to write but still force an amount of noise,
|
|
mostly MPL types, so it would be nice to write code looking like C++ (with a C++
|
|
action language) directly inside the transition table, like UML designers like to do
|
|
on their state machine diagrams. This is what eUML is for.</p><p>eUML is a Boost.Proto-based compile-time domain specific embedded language. It
|
|
provides grammars which allow the definition of actions/guards directly inside the
|
|
transition table or entry/exit in the state definition. It is defined in the
|
|
namespace msm::front::euml. There are grammars for actions, guards, flags,
|
|
attributes, deferred events, initial states.</p><p>It also relies on Boost.Typeof as a wrapper around the new decltype C++0x feature
|
|
to provide a compile-time evaluation of all the grammars. Unfortunately, all the
|
|
underlying Boost libraries are not Typeof-enabled, so for the moment, you will need
|
|
a compiler where Typeof is natively implemented (like VC8-9-10, g++ >= 4.3).</p><p>Examples will be provided in the next paragraphs. You need to include eUML basic
|
|
features: </p><p><code class="code">#include <msm/front/euml/euml.hpp></code></p><p>To add STL support (at possible cost of longer compilation times), include: </p><p><code class="code">#include <msm/front/euml/stl.hpp></code></p><div class="sect3" title="Transition table"><div class="titlepage"><div><div><h4 class="title"><a name="d0e2501"></a>Transition table</h4></div></div></div><p>A transition can be defined using eUML as: </p><p><code class="code">source + event [guard] / action == target</code> or as</p><p><code class="code">target == source + event [guard] / action</code></p><p>The first version looks like a drawn transition in a diagram, the second one
|
|
seems natural to a C++ developper.</p><p>The simple transition table written with the <span class="command"><strong><a class="command" href="ar01s04.html#functor-front-end">previous front-end</a></strong></span> can now be
|
|
written as:</p><p>
|
|
</p><table frame="void" id="d0e2522"><tbody><tr>
|
|
<td>typedef BOOST_TYPEOF(build_stt((</td>
|
|
<td> </td>
|
|
<td> </td>
|
|
</tr><tr>
|
|
<td>Stopped +</td>
|
|
<td>play [DummyGuard] / (TestFct,start_playback)</td>
|
|
<td>== Playing</td>
|
|
</tr><tr>
|
|
<td>Stopped +</td>
|
|
<td>open_close/ open_drawer</td>
|
|
<td>== Open</td>
|
|
</tr><tr>
|
|
<td>Stopped +</td>
|
|
<td>stop</td>
|
|
<td>== Stopped</td>
|
|
</tr><tr>
|
|
<td>Open +</td>
|
|
<td>open_close / close_drawer</td>
|
|
<td>== Empty</td>
|
|
</tr><tr>
|
|
<td>Empty +</td>
|
|
<td>open_close / open_drawer </td>
|
|
<td>== Open</td>
|
|
</tr><tr>
|
|
<td>Empty +</td>
|
|
<td>cd_detected [good_disk_format] / store_cd_info </td>
|
|
<td>== Stopped</td>
|
|
</tr><tr>
|
|
<td> ) ) ) transition_table;</td>
|
|
<td> </td>
|
|
<td> </td>
|
|
</tr></tbody></table><p>
|
|
</p><p>Or, using the alternative notation, it can be:</p><p>
|
|
</p><table id="d0e2617"><tbody><tr>
|
|
<td>typedef BOOST_TYPEOF(build_stt((</td>
|
|
<td> </td>
|
|
<td> </td>
|
|
</tr><tr>
|
|
<td>Playing == </td>
|
|
<td>Stopped +</td>
|
|
<td>play [DummyGuard] / (TestFct,start_playback)</td>
|
|
</tr><tr>
|
|
<td>Open ==</td>
|
|
<td>Stopped +</td>
|
|
<td>open_close/ open_drawer</td>
|
|
</tr><tr>
|
|
<td>Stopped ==</td>
|
|
<td>Stopped +</td>
|
|
<td>stop</td>
|
|
</tr><tr>
|
|
<td>Empty ==</td>
|
|
<td>Open +</td>
|
|
<td>open_close / close_drawer</td>
|
|
</tr><tr>
|
|
<td>Open ==</td>
|
|
<td>Empty +</td>
|
|
<td>open_close / open_drawer</td>
|
|
</tr><tr>
|
|
<td>Stopped ==</td>
|
|
<td>Empty +</td>
|
|
<td>cd_detected [good_disk_format] / store_cd_info </td>
|
|
</tr><tr>
|
|
<td> ) ) ) transition_table;</td>
|
|
<td> </td>
|
|
<td> </td>
|
|
</tr></tbody></table><p>
|
|
</p><p>The transition table now looks like a list of (readable) rules with little
|
|
noise.</p><p>UML defines guards between “[ ]” and actions after a “/”, so this is already
|
|
more readable for UML designers. UML also allows designers to define several
|
|
actions sequentially (our previous ActionSequence) separated by a comma. The
|
|
first transition does just this: two actions separated by a comma and enclosed
|
|
inside parenthesis to respect C++ operator precedence.</p><p>If this seems to you like it will cost you run-time performance, don't worry,
|
|
typeof (decltype) only evaluates the build_stt function and no run-time cost
|
|
occurs. Actually, eUML is only a metaprogramming layer on top of "standard" MSM
|
|
metaprogramming and this first layer generates the previously-presented <span class="command"><strong><a class="command" href="ar01s04.html#functor-front-end">functor front-end</a></strong></span>.</p><p>UML also allows designers to define more complicated guards, like
|
|
[good_disk_format && (some_condition || some_other_condition)]. This was
|
|
possible with our previously defined functors, but using a complicated template
|
|
syntax. This syntax is now possible exactly as written, which means without
|
|
syntactic noise.</p></div><div class="sect3" title="Defining events, actions and states with entry/exit actions"><div class="titlepage"><div><div><h4 class="title"><a name="d0e2719"></a>Defining events, actions and states with entry/exit actions</h4></div></div></div><p>Events must be proto-enabled. To achieve this, they must inherit from
|
|
euml_event:</p><p><code class="code">struct play : euml_event<play>{};</code></p><p>Actions (returning void) and guards (returning a bool) are defined like
|
|
previous functors, with the difference that they also must be
|
|
proto-enabled:</p><p><code class="code">struct some_condition : euml_action< some_condition ></code></p><p><code class="code">{ </code></p><p><code class="code">template <class Fsm,class Evt,class SourceState,class
|
|
TargetState></code></p><p><code class="code">bool operator()(Evt const& ,Fsm& ,SourceState&
|
|
,TargetState& ) { return true; } </code></p><p><code class="code">}; </code></p><p>It is also possible to use the same action grammar as for the transition table
|
|
for state entry and exit actions:</p><p><code class="code">typedef BOOST_TYPEOF(euml::build_state( (Empty_Entry,Dummy_Entry)/*2
|
|
entry actions*/,Empty_Exit/*1 exit action*/ )) Empty;</code></p><p>This means that Empty is defined as a state with an entry action made of two
|
|
sub-actions, Empty_Entry and Dummy_Entry (enclosed inside parenthesis), and an
|
|
exit action, Empty_Exit.</p><p>There are several overloads of the <span class="command"><strong><a name="eUML-build-state"></a></strong></span>build_state function:</p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>build_state(): state without entry or exit action.</p></li><li class="listitem"><p>build_state(Expr1): state with entry but no exit action.</p></li><li class="listitem"><p>build_state(Expr1,Expr2): state with entry and exit action.</p></li><li class="listitem"><p>build_state(Expr1,Expr2,Attributes): state with entry and exit
|
|
action, defining some attributes (read further on).</p></li><li class="listitem"><p>build_state(Expr1,Expr2,Attributes,Configure): state with entry
|
|
and exit action, defining some attributes (read further on) and
|
|
flags (standard MSM flags) or deferred events (standard MSM deferred
|
|
events).</p></li><li class="listitem"><p>build_state(Expr1,Expr2,Attributes,Configure,Base): state with
|
|
entry and exit action, defining some attributes (read further on),
|
|
flags and deferred events (plain msm deferred events) and a
|
|
non-default base state (as defined in standard MSM).</p></li></ul></div><p>A NoAction is also defined, which does, well, nothing except being a
|
|
placeholder (needed for example as entry action if we have no entry but an
|
|
exit). Expr1 and Expr2 are a sequence of actions, obeying the same action
|
|
grammar as in the transition table (following the “/” symbol).</p><p>The state functors have a slightly different signature as there is no source
|
|
and target state but only a current state (entry/exit actions are
|
|
transition-independent), for example:</p><p><code class="code">struct Empty_Entry : euml_action< Empty_Entry ></code></p><p><code class="code">{ </code></p><p><code class="code">template <class Evt,class Fsm,class State></code></p><p><code class="code">void operator()(Evt const& ,Fsm& ,State& ) { ... }
|
|
</code></p><p><code class="code">}; </code></p><p>Notice again the euml_action, to make the functor play nice with the grammar.
|
|
</p></div><div class="sect3" title="Defining a simple state machine"><div class="titlepage"><div><div><h4 class="title"><a name="d0e2795"></a>Defining a simple state machine</h4></div></div></div><p>Like for a functor front-end, you can reuse the state machine definition
|
|
method from the standard front-end. You can also use eUML to define a state
|
|
machine "on the fly" (if, for example, you need to provide an on_entry/on_exit
|
|
for this state machine as a functor). For this, there is also a function,
|
|
<span class="command"><strong><a name="eUML-build-sm"></a></strong></span>build_sm, which has up to 8 arguments:</p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>build_sm(Stt, Init): simplest state machine where only the
|
|
transition table and initial state(s) are defined.</p></li><li class="listitem"><p>build_sm(Stt, Init, Expr1): state machine where the transition
|
|
table, initial state and entry action are defined.</p></li><li class="listitem"><p>build_sm(Stt, Init, Expr1, Expr2): state machine where the
|
|
transition table, initial state, entry and exit actions are
|
|
defined.</p></li><li class="listitem"><p>build_sm(Stt, Init, Expr1, Expr2, Attributes): state machine where
|
|
the transition table, initial state, entry and exit actions are
|
|
defined. Furthermore, some attributes are added (read further
|
|
on).</p></li><li class="listitem"><p>build_sm(Stt, Init, Expr1, Expr2, Attributes, Configure): state
|
|
machine where the transition table, initial state, entry and exit
|
|
actions are defined. Furthermore, some attributes (read further on),
|
|
flags, deferred events and configuration capabilities TODO link (no
|
|
message queue / no exception catching) are added.</p></li><li class="listitem"><p>build_sm(Stt, Init, Expr1, Expr2, Attributes, Flags, Deferred ,
|
|
Base): state machine where the transition table, initial state,
|
|
entry and exit actions are defined. Furthermore, attributes (read
|
|
further on), flags , deferred events and configuration capabilities
|
|
(no message queue / no exception catching) are added and a
|
|
non-default base state (see base state TODO) is defined.</p></li></ul></div><p>For example, a minimum state machine could be defined
|
|
like:</p><p>
|
|
</p><table id="d0e2824"><tbody><tr>
|
|
<td>typedef BOOST_TYPEOF(build_stt((</td>
|
|
<td> </td>
|
|
<td> </td>
|
|
</tr><tr>
|
|
<td>... ) ) ) transition_table;</td>
|
|
<td> </td>
|
|
<td> </td>
|
|
</tr></tbody></table><p>
|
|
</p><p><code class="code">typedef BOOST_TYPEOF(build_sm( transition_table(),init_ << Empty
|
|
)) player_;</code></p><p><span class="underline">Note for VC9</span>: This defined build_sm
|
|
syntax works most of the time. But once in a while, VC9 will display the problem
|
|
shown in the next section (not enough heap space). For example, this simple
|
|
performance test (TODO link), while really simple, will display the bug. To
|
|
correct it, the following solution works: </p><p><code class="code">#ifndef BOOST_MSVC</code></p><p><code class="code">typedef BOOST_TYPEOF(build_sm( transition_table(),init_ << Empty
|
|
<< AllOk )) player_;</code></p><p><code class="code">#else</code></p><p><code class="code">struct player_ : public BOOST_TYPEOF(build_sm( transition_table(),init_
|
|
<< Empty << AllOk )) {};</code></p><p><code class="code">#endif</code></p><p>Please have a look at the player tutorial written using eUML's <a class="link" href="examples/SimpleTutorialEuml2.cpp" target="_top">first</a> and <a class="link" href="examples/SimpleTutorialEuml.cpp" target="_top">second</a> syntax. Please
|
|
ignore for the moment the BOOST_MSM_EUML_DECLARE_ATTRIBUTE macros, we come back
|
|
to it very soon.</p></div><div class="sect3" title="Defining a submachine"><div class="titlepage"><div><div><h4 class="title"><a name="d0e2879"></a>Defining a submachine</h4></div></div></div><p>Defining a submachine (see <a class="link" href="examples/CompositeTutorialEuml.cpp" target="_top">tutorial</a>) with other
|
|
front-ends simply means using a state which is a state machine in the transition
|
|
table of another state machine. This is the same with eUML. One only needs
|
|
define a second state machine and reference it in the transition table of the
|
|
containing state machine.</p><p><span class="underline">Note</span>: the previous #ifdef trick has to
|
|
be used for submachine definition because the VC9 bug occurs more often when
|
|
submachines are involved.</p></div><div class="sect3" title="Attributes / Function call"><div class="titlepage"><div><div><h4 class="title"><a name="d0e2891"></a> Attributes / Function call</h4></div></div></div><p>We now want to make our grammar more useful. Very often, one needs only very
|
|
simple action methods, for example ++Counter or Counter > 5 where Counter is
|
|
usually defined as some attribute of the class containing the state machine.
|
|
Furthermore, unlike many expensive tools which are on the market, states within
|
|
MSM are also classes so they can have attributes, and we would also like to
|
|
provide them with attributes. </p><p>If you look back at our examples using the <a class="link" href="examples/SimpleTutorialEuml2.cpp" target="_top">first</a> and <a class="link" href="examples/SimpleTutorialEuml.cpp" target="_top">second</a> syntaxes, you
|
|
will find some unexplained BOOST_MSM_EUML_DECLARE_ATTRIBUTE macros. Let us go
|
|
back to them. We have:</p><p><code class="code">BOOST_MSM_EUML_DECLARE_ATTRIBUTE(std::string,cd_name)</code></p><p><code class="code">BOOST_MSM_EUML_DECLARE_ATTRIBUTE(DiskTypeEnum,cd_type)</code></p><p>This declares two attributes: cd_name of type std::string and cd_type of type
|
|
DiskTypeEnum. These attributes are not part of any event or state in particular,
|
|
we just declared a name and a type. Now, we can add attributes to our
|
|
cd_detected event:</p><p><code class="code">typedef BOOST_TYPEOF(build_attributes(attributes_ << cd_name
|
|
<< cd_type )) cd_detected_attributes;</code></p><p><code class="code">struct cd_detected : euml_event<cd_detected>,cd_detected_attributes
|
|
{</code></p><p><code class="code">cd_detected(std::string name, DiskTypeEnum diskType) {</code></p><p><code class="code">get_attribute(cd_name)=name;get_attribute(cd_type)=diskType;}</code></p><p><code class="code">};</code></p><p>The two left shift of the first line add both attributes into the helper
|
|
cd_detected_attributes structure. As cd_detected inherits from the helper, it
|
|
now has these two attributes. The function get_attribute returns a reference to
|
|
the required attributes so that we can easily write and set them.</p><p>Ok, great, we now have a two liner to add attributes to a class, which we
|
|
could have done more easily, so what is the point? The point is that we can now
|
|
do what was not possible, reference these attributes directly, at compile-time,
|
|
in the transition table. For example, in the example, you will find this
|
|
transition:</p><p><code class="code">Stopped == Empty + cd_detected [good_disk_format &&
|
|
(event_(cd_type)==Int_<DISK_CD>())] </code></p><p>Read event_(cd_type) as event_->cd_type with event_ a type generic for events,
|
|
whatever the concrete event is (in this particular case, it happens to be a
|
|
cd_detected as the transition shows).</p><p>The main advantage of this feature is that you do not need to define a new
|
|
functor and you do not need to look inside the functor to know what it does, you
|
|
have all at hand.</p><p>MSM provides more generic objects for state machine types:</p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>event_ : used inside any action, the event triggering the
|
|
transition</p></li><li class="listitem"><p>state_: used inside entry and exit actions, the entered / exited
|
|
state</p></li><li class="listitem"><p>source_: used inside a transition action, the source state</p></li><li class="listitem"><p>target_: used inside a transition action, the target state</p></li><li class="listitem"><p>fsm_: used inside any action, the (lowest-level) state machine
|
|
processing the transition</p></li><li class="listitem"><p>Int_<int value>: a functor representing an int</p></li><li class="listitem"><p>Char_<value>: a functor representing a char</p></li><li class="listitem"><p>Size_t_<value>: a functor representing a size_t</p></li><li class="listitem"><p>String_<mpl::string> (boost >= 1.40): a functor representing a
|
|
string.</p></li></ul></div><p>These helpers can be used in two different ways:</p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>helper(attribute_name) returns the attribute with name
|
|
attribute_name</p></li><li class="listitem"><p>helper returns the state / event type itself.</p></li></ul></div><p>The second form is helpful if you want to use states with self-created
|
|
functors. In the <a class="link" href="examples/SimpleTutorialEuml.cpp" target="_top">above
|
|
tutorial</a>, we provide Empty with an activate_empty method. We would
|
|
like to create a eUML functor and call it from inside the transition table. This
|
|
is done using the MSM_EUML_METHOD / MSM_EUML_FUNCTION macros. The first creates
|
|
a functor to a method, the second to a free function. In the tutorial, we
|
|
write:</p><p><code class="code">MSM_EUML_METHOD(ActivateEmpty_ , activate_empty , activate_empty_ , void
|
|
, void )</code></p><p>The first parameter is the functor name, for use either directly or with the
|
|
functor front-end. The second is the name of the method which will be called.
|
|
The third is the function name for use in the transition table, the fourth is
|
|
the return type of the function if used in the context of a transition action,
|
|
the fifth is the result type if used in the context of a state entry / exit
|
|
action (usually fourth and fifth are the same). We now have a new eUML function
|
|
calling a method of "something", and this "something" is one of the five
|
|
previously explained helpers. We can now use this in a transition, for
|
|
example:</p><p><code class="code">Empty == Open + open_close /
|
|
(close_drawer,activate_empty_(target_))</code></p><p>The action is now defined as a sequence of two actions: close_drawer and
|
|
activate_empty called on the target itself. The target being Empty (the state
|
|
defined left), this really will call Empty.activate_empty(). This method could
|
|
also have an (or several) argument(s), for example the event, we could then call
|
|
activate_empty_(target_ , event_).</p><p>More examples can be found in the <a class="link" href="examples/CompilerStressTestEuml.cpp" target="_top">terrible compiler stress
|
|
test</a>, the <a class="link" href="examples/SimpleTimer.cpp" target="_top">timer
|
|
example</a> or in the <a class="link" href="examples/iPodSearchEuml.cpp" target="_top">iPodSearch with eUML</a> (for String_ and more).</p></div><div class="sect3" title="Orthogonal regions, flags, event deferring"><div class="titlepage"><div><div><h4 class="title"><a name="d0e3003"></a>Orthogonal regions, flags, event deferring</h4></div></div></div><p>To define orthogonal regions really means defining more initial states. To add
|
|
more initial states, “shift left” some, for example, if we had another initial
|
|
state named AllOk :</p><p><code class="code">typedef BOOST_TYPEOF(build_sm( transition_table(),init_ << Empty
|
|
<< AllOk )) player_;</code></p><p>You remember from the <span class="command"><strong><a class="command" href="ar01s04.html#eUML-build-state">build_state</a></strong></span> and <span class="command"><strong><a class="command" href="ar01s04.html#eUML-build-sm">build_sm</a></strong></span> signatures that just after attributes, we can define
|
|
flags, like in the basic MSM frontend. To do this, we have another "shift-left"
|
|
grammar, for example:</p><p><code class="code">typedef BOOST_TYPEOF(build_state(NoAction,NoAction, attributes_ <<
|
|
no_attributes_, </code></p><p><code class="code">/* flags */ configure_<< PlayingPaused << CDLoaded ))
|
|
Paused; </code></p><p>We now defined that Paused will get two flags, PlayingPaused and CDLoaded,
|
|
defined, for example as:</p><p><code class="code">struct CDLoaded : euml_flag<CDLoaded> {};</code></p><p>This corresponds to the following basic front-end definition of Paused:</p><p><code class="code">struct Paused : public msm::front::state<> </code></p><p><code class="code">{ typedef mpl::vector2<PlayingPaused,CDLoaded> flag_list; };
|
|
</code></p><p>Under the hood, what you get really is a mpl::vector2.</p><p><span class="underline">Note</span>: As we use the version of
|
|
build_state with 4 arguments, we need to tell eUML that we need no attributes.
|
|
Similarly to a <code class="code">cout << endl</code>, we need a <code class="code">attributes_
|
|
<< no_attributes_</code> syntax.</p><p>You can use the flag with the is_flag_active method of a state machine. You
|
|
can also use the provided helper function is_flag_ (returning a bool) for state
|
|
and transition actions. For example, in the iPod implementation with eUML (TODO
|
|
link), you find the following transition:</p><p><code class="code">ForwardPressed == NoForward + EastPressed
|
|
[!is_flag_(NoFastFwd)]</code></p><p>The function also has an optional second parameter which is the state machine
|
|
on which the function is called. by default, fsm_ is used (the current state
|
|
machine) but you could provide a functor returning a reference to another state
|
|
machine.</p><p>eUML also supports defining deferred events in the state (state machine)
|
|
definition. To this aim, we can reuse the flag grammar. For example:</p><p><code class="code">typedef BOOST_TYPEOF(build_state(Empty_Entry,Empty_Exit, attributes_
|
|
<< no_attributes_, </code></p><p><code class="code">/* flags */ configure_<< play )) Empty; </code></p><p>The configure_ left shift is also responsible for deferring events. Shit
|
|
inside a flag and it will be seen as a flag, shift an event and it will be a
|
|
deferred event. This replaces the basic front-end definition:</p><p><code class="code">typedef mpl::vector<play> deferred_events;</code></p><p>In <a class="link" href="examples/OrthogonalDeferredEuml.cpp" target="_top">this
|
|
tutorial</a>, player is defining a second orthogonal region with AllOk as
|
|
initial state. The <code class="code">Empty</code> and <code class="code">Open</code> states also defer
|
|
the event <code class="code">play</code>. <code class="code">Open</code>, <code class="code">Stopped</code> and
|
|
<code class="code">Pause</code> also support the flag <code class="code">CDLoaded</code> using the
|
|
same left shift into <code class="code">configure_</code>.</p><p>In the functor front_end, we also had the possibility to defer an event inside
|
|
a transition, which makes possible conditional deferring. This is also possible
|
|
with eUML through the use of the defer_ order, as shown in <a class="link" href="examples/OrthogonalDeferredEuml.cpp" target="_top">this tutorial</a>. You
|
|
will find the foillowing transition:</p><p><code class="code">Open + play / defer_</code></p><p>This is an <span class="command"><strong><a class="command" href="ar01s04.html#eUML-internal">internal transition</a></strong></span>.
|
|
Ignore it for the moment. Interesting is, that when the event <code class="code">play</code>
|
|
is fired and <code class="code">Open</code> is active, the event will be deferred. Now add a
|
|
guard and you can conditionally defer the event, for example:</p><p><code class="code">Open + play [ some_condition ] / defer_</code></p><p>This is similar to what we did with the functor front-end. This means that we
|
|
have the same limitations. Using defer_ instead of a state declaration, we need
|
|
to tell MSM that we have deferred events in this state machine. We do this
|
|
(again) using a configure_ declaration in the state machine definition in which
|
|
we shift the deferred_events configuration flag using the build_sm
|
|
function:</p><p><code class="code">typedef BOOST_TYPEOF(build_sm( transition_table(),init_ << Empty
|
|
<< AllOk,</code></p><p><code class="code">Entry_Action, Exit_Action, attributes_ << no_attributes_,
|
|
configure_<< deferred_events )) player_;</code></p><p>A <a class="link" href="examples/OrthogonalDeferredEuml2.cpp" target="_top">tutorial</a>
|
|
illsutrates this possibility.</p></div><div class="sect3" title="Customizing a state machine / Getting more speed"><div class="titlepage"><div><div><h4 class="title"><a name="d0e3134"></a> Customizing a state machine / Getting more speed</h4></div></div></div><p>We just saw how to use configure_ to define deferred events or flags. We can
|
|
also use it to configure our state machine like we did with other front-ends
|
|
(TODO add in standard):</p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>configure_ << no_exception: disables exception
|
|
handling</p></li><li class="listitem"><p>configure_ << no_msg_queue deactivates the message
|
|
queue</p></li></ul></div><p>Deactivating these features if not needed greatly improves the event
|
|
dispatching speed of your state machine. Our <a class="link" href="examples/EumlSimple.cpp" target="_top">speed testing</a> example with eUML
|
|
use this feature.</p></div><div class="sect3" title="Anonymous transitions"><div class="titlepage"><div><div><h4 class="title"><a name="d0e3151"></a>Anonymous transitions</h4></div></div></div><p>Anonymous transitions (See <span class="command"><strong><a class="command" href="ar01s03.html#uml-anonymous">UML
|
|
tutorial</a></strong></span>) are transitions without a named event which are
|
|
therefore triggered immediately when the source state becomre active, provided a
|
|
guard allows it. As there is no event, to define such a transition, simply omit
|
|
the “+” part of the transition (the event), for example: </p><p><code class="code">State3 == State4 [always_true] / State3ToState4</code></p><p><code class="code">State4 [always_true] / State3ToState4 == State3</code></p><p>Please have a look at <a class="link" href="examples/AnonymousTutorialEuml.cpp" target="_top">this example</a>, which implements the <span class="command"><strong><a class="command" href="ar01s04.html#anonymous-transitions">previously defined</a></strong></span> state
|
|
machine with eUML.</p></div><div class="sect3" title="Internal transitions"><div class="titlepage"><div><div><h4 class="title"><a name="d0e3173"></a><span class="command"><strong><a name="eUML-internal"></a></strong></span>Internal transitions</h4></div></div></div><p>Like both other front-ends, eUML supports two ways of defining internal transitions:</p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>in the state machine's transition table. In this case, you need to
|
|
specify a source state, event, actions and guards but no target
|
|
state, which eUML will interpret as an internal transition, for
|
|
example this defines a transition internal to Open, on the event
|
|
open_close:</p><p><code class="code">Open + open_close [internal_guard1] /
|
|
internal_action1</code></p><p><a class="link" href="examples/EumlInternal.cpp" target="_top">A full example</a>
|
|
is also provided.</p></li><li class="listitem"><p>in a state's <code class="code">internal_transition_table</code>. For
|
|
example:</p><p><code class="code">typedef BOOST_TYPEOF(build_state( Open_Entry(),Open_Exit()
|
|
)) Open_def;</code></p><p><code class="code">struct Open : public Open_def {</code></p><p><code class="code">typedef BOOST_TYPEOF(build_internal_stt((</code></p><p><code class="code">open_close [internal_guard1] /
|
|
internal_action1</code></p><p><code class="code">) ) ) internal_transition_table;</code></p><p><code class="code">};</code></p><p>Notice how we do not need to repeat that the transition originates
|
|
from Open as we already are in the context of Open. </p><p>The <a class="link" href="examples/EumlInternalDistributed.cpp" target="_top">implementation</a> also shows the added bonus offered for
|
|
submachines, which can have both the standard transition_table and
|
|
an internal_transition_table (which has higher priority). This makes
|
|
it easier if you decide to make a full submachine from a state. It
|
|
is also slightly faster than the standard alternative, adding
|
|
orthogonal regions, because event dispatching will, if accepted by
|
|
the internal table, not continue to the subregions. This gives you a
|
|
O(1) dispatch instead of O(number of regions).</p></li></ul></div></div><div class="sect3" title="Direct entry / entry and exit pseudo-state / fork"><div class="titlepage"><div><div><h4 class="title"><a name="d0e3221"></a>Direct entry / entry and exit pseudo-state / fork</h4></div></div></div><p>We saw the <span class="command"><strong><a class="command" href="ar01s04.html#eUML-build-state">build_state</a></strong></span>
|
|
function, which creates a simple state. Likewise, eUML provides other
|
|
state-building functions for other types of states:</p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>build_terminal_state takes the same arguments as build_state and
|
|
defines, well, a terminate state.</p></li><li class="listitem"><p>build_interrupt_state takes the same arguments as build_state and
|
|
defines an interrupt state.</p></li><li class="listitem"><p>build_exit_state takes the same arguments as build_state and
|
|
defines an exit pseudo state.</p></li><li class="listitem"><p>build_entry_state takes the same arguments as build_state and
|
|
defines an interrupt state. The region index to be entered is
|
|
defined as an int template argument, so build_entry_state<0>
|
|
defines an entry state into the first region of a submachine.</p></li><li class="listitem"><p>build_explicit_entry_state takes the same arguments as build_state
|
|
and defines an explicit entry state. The region index to be entered
|
|
is defined as an int template argument, so
|
|
build_explicit_entry_state<0> defines an explicit entry state
|
|
into the first region of a submachine.</p></li></ul></div><p>Using these states in the transition table is like in any other front end
|
|
using fsm_name::exit_pt<>, fsm_name::direct<> and fsm_name::entry_pt<>.
|
|
For example, a direct entry could be:</p><p><code class="code">SubFsm2::direct<SubState2> == State1 + event2</code></p><p>Forks being a list on direct entries, eUML supports a logical syntax (state1,
|
|
state2, ...), for example:</p><p><code class="code">(SubFsm2::direct<SubState2>, SubFsm2::direct<SubState2b>,
|
|
SubFsm2::direct<SubState2c>) == State1 + event3</code></p><p>The <a class="link" href="examples/DirectEntryEuml.cpp" target="_top">entry tutorial</a> is
|
|
also available with eUML.</p></div><div class="sect3" title="Helper functions"><div class="titlepage"><div><div><h4 class="title"><a name="d0e3260"></a>Helper functions</h4></div></div></div><p>We saw a few helpers but there are more, so let us have a more complete description:</p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>event_ : used inside any action, the event triggering the
|
|
transition</p></li><li class="listitem"><p>state_: used inside entry and exit actions, the entered / exited
|
|
state</p></li><li class="listitem"><p>source_: used inside a transition action, the source state</p></li><li class="listitem"><p>target_: used inside a transition action, the target state</p></li><li class="listitem"><p>fsm_: used inside any action, the (lowest-level) state machine
|
|
processing the transition</p></li><li class="listitem"><p>The previous objects can also return an attribute, for example
|
|
event_(cd_name)</p></li><li class="listitem"><p>Int_<int value>: a functor representing an int</p></li><li class="listitem"><p>Char_<value>: a functor representing a char</p></li><li class="listitem"><p>Size_t_<value>: a functor representing a size_t</p></li><li class="listitem"><p>True_ and False_ functors returning true and false
|
|
respectively</p></li><li class="listitem"><p>String_<mpl::string> (boost >= 1.40): a functor representing a
|
|
string.</p></li><li class="listitem"><p>if_then_else_(guard, action, action) where action can be an action
|
|
sequence</p></li><li class="listitem"><p>if_then_(guard, action) where action can be an action
|
|
sequence</p></li><li class="listitem"><p>while_(guard, action) where action can be an action
|
|
sequence</p></li><li class="listitem"><p>do_while_(guard, action) where action can be an action
|
|
sequence</p></li><li class="listitem"><p>for_(action, guard, action, action) where action can be an action
|
|
sequence</p></li><li class="listitem"><p>process_(some_event [, some state machine] [, some state machine]
|
|
[, some state machine] [, some state machine]) will call
|
|
process_event (some_event) on the current state machine or on the
|
|
one(s) passed as 2nd , 3rd, 4th, 5th argument. This allow sending
|
|
events to several external machines</p></li><li class="listitem"><p>process2_(some_event,Value [, some state machine] [, some state
|
|
machine] [, some state machine]) will call process_event
|
|
(some_event(Value)) on the current state machine or on the one(s)
|
|
passed as 3rd, 4th, 5th argument</p></li><li class="listitem"><p>is_ flag_(some_flag[, some state machine]) will call
|
|
is_flag_active on the current state machine or on the one passed as
|
|
2nd argument</p></li><li class="listitem"><p>Predicate_<some predicate>: Used in STL algorithms. Wraps
|
|
unary/binary functions to make them eUML-compatible so that they can
|
|
be used in STL algorithms</p></li></ul></div><p>This can make for quite some fun. For example, </p><p><code class="code">/( if_then_else_(--fsm_(m_SongIndex) > Int_<0>(),/*if
|
|
clause*/</code></p><p><code class="code">show_playing_song(), /*then clause*/</code></p><p><code class="code">(fsm_(m_SongIndex)=Int_<1>(),process_(EndPlay())) /*else clause*/ )
|
|
)</code> means:</p><p>if (fsm.SongIndex > 0, call show_playing_song else {fsm.SongIndex=1; process
|
|
EndPlay on fsm;}</p><p>A few examples are using these features:</p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>the iPod example introduced at the BoostCon09 <a class="link" href="examples/iPodEuml.cpp" target="_top">has been rewritten</a>
|
|
with eUML (weak compilers please move on...)</p></li><li class="listitem"><p>the iPodSearch example also introduced at the BoostCon09 <a class="link" href="examples/iPodSearchEuml.cpp" target="_top">has been
|
|
rewritten</a> with eUML. In this example, you will also find
|
|
some examples of STL functor usage.</p></li><li class="listitem"><p><a class="link" href="examples/SimpleTimer.cpp" target="_top">A simpler timer</a>
|
|
example is a good starting point. </p></li></ul></div><p>There is unfortunately a small catch. Defining a functor using MSM_EUML_METHOD
|
|
or MSM_EUML_FUNCTION will create a correct functor. Your own eUML functors
|
|
written as described at the beginning of this section will also work well,
|
|
<span class="underline">except</span> with the while_, if_then_,
|
|
if_then_else_ functions which will require a bit of writing. TODO macro.</p></div><div class="sect3" title="Phoenix-like STL support"><div class="titlepage"><div><div><h4 class="title"><a name="d0e3365"></a>Phoenix-like STL support</h4></div></div></div><p>As we saw, eUML supports most C++ operators (except address-of). For example
|
|
it is possible to write event_(some_attribute)++ or [source_(some_bool)
|
|
&& fsm_(some_other_bool)]. But a programmer needs more than operators in
|
|
his daily programming. The STL is clearly a must have. Therefore, eUML comes in
|
|
with a lot of functors to simplify your day-to-day programming. For almost every
|
|
algorithm or container method of the STL, a corresponding eUML function is
|
|
defined. Like Boost.Phoenix, “.” And “->” of call on objects are replaced by a
|
|
functional programming paradigm, for example:</p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>begin_(container), end_(container): returns iterators of a
|
|
container.</p></li><li class="listitem"><p>empty_(container): returns container.empty()</p></li><li class="listitem"><p>clear_(container): container.clear()</p></li><li class="listitem"><p>transform_ : std::transform</p></li></ul></div><p>In a nutshell, almost every STL method or algorithm is matched by a
|
|
corresponding functor, which can then be used in the transition table or state
|
|
actions. The reference (TODO link) explains in detail the usage and the
|
|
underlying functor (so that this possibility is not reserved to eUML but also to
|
|
the functor-based front-end). The file structure of this Phoenix-like library
|
|
matches the one of Boost.Phoenix. All STL algorithm functors are to be found
|
|
in:</p><p><code class="code">#include <msm/front/euml/algorithm.hpp></code></p><p>The algorithms are also divided into sub-headers, matching the phoenix
|
|
structure for simplicity:</p><p><code class="code">#include < msm/front/euml/iteration.hpp> </code></p><p><code class="code">#include < msm/front/euml/transformation.hpp> </code></p><p><code class="code">#include < msm/front/euml/querying.hpp> </code></p><p>Container methods can be found in:</p><p><code class="code">#include < msm/front/euml/container.hpp></code></p><p>Or one can simply include the whole STL support (you will also need to include
|
|
euml.hpp):</p><p><code class="code">#include < msm/front/euml/stl.hpp></code></p><p>A few examples (to be found in <a class="link" href="examples/iPodSearchEuml.cpp" target="_top">this tutorial</a>):</p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p><code class="code">push_back_(fsm_(m_tgt_container),event_(m_song))</code>: the
|
|
state machine has an attribute m_tgt_container of type
|
|
std::vector<OneSong> and the event has an attribute m_song of
|
|
type OneSong. The line therefore pushes m_song at the end of
|
|
m_tgt_container</p></li><li class="listitem"><p><code class="code">if_then_( state_(m_src_it) != end_(fsm_(m_src_container)),
|
|
process2_(OneSong(),*(state_(m_src_it)++)) )</code>: the current
|
|
state has an attribute m_src_it (an iterator). If this iterator !=
|
|
fsm.m_src_container.end(), process OneSong on fsm, copy-constructed
|
|
from state.m_src_it which we post-increment</p></li></ul></div></div></div><div class="sect2" title="Back-end"><div class="titlepage"><div><div><h3 class="title"><a name="d0e3425"></a>Back-end</h3></div></div></div><p>There is, at the moment, one back-end. This back-end contains the library engine
|
|
and defines the performance and functionality tradeoffs. The currently available
|
|
back-end implements most of the functionality defined by the UML 2.0 standard at
|
|
very high runtime speed, in exchange for longer compile-time. The runtime speed is
|
|
due to a constant-time double-dispatch and self-adapting capabilities allowing the
|
|
framework to adapt itself to the features used by a given concrete state machine.
|
|
All unneeded features either disable themselves or can be manually disabled. See
|
|
section 5.1 for a complete description of the run-to-completion algorithm.</p><div class="sect3" title="MSM Backend features"><div class="titlepage"><div><div><h4 class="title"><a name="d0e3430"></a> MSM Backend features </h4></div></div></div><p>TODO</p><p></p><div class="sect4" title="Creation"><div class="titlepage"><div><div><h5 class="title"><a name="d0e3436"></a> Creation </h5></div></div></div><p> MSM being divided betwenn front and back-end, one needs to first define a
|
|
front-end. Then, to create a real state machine, the back-end must be
|
|
created: <code class="code">typedef msm::back::state_machine<my_front_end>
|
|
my_fsm;</code>
|
|
</p><p>We now have a fully functional state machine. The next sections will
|
|
describe what can be done with it.</p></div><div class="sect4" title="Event dispatching"><div class="titlepage"><div><div><h5 class="title"><a name="d0e3446"></a>Event dispatching</h5></div></div></div><p>The main reason to exist for a state machine is to dispatch events. For
|
|
MSM, events are objects of a given event type. The object itself can contain
|
|
data, but the event type is what decides of the transition to be taken. For
|
|
MSM, if some_event is a given type (a simple struct for example) and e1 and
|
|
e2 concrete events, e1 and e2 are equivalent, from a transition perspective.
|
|
Of course, e1 and e2 can have different values and you can use them inside
|
|
actions. Events are dispatched as const reference, so actions cannot modify
|
|
events for obvious side-effect reasons. To dispatch an event of type
|
|
some_event, you can simply write: </p><p><code class="code">my_fsm fsm; fsm.process_event(some_event());</code></p><p><code class="code">some_event e1; fsm.process_event(e1)</code></p><p>Creating an event on the fly will be optimized by the compiler so the
|
|
performance will not degrade.</p></div><div class="sect4" title="Active state(s)"><div class="titlepage"><div><div><h5 class="title"><a name="d0e3459"></a>Active state(s)</h5></div></div></div><p>The backend also offers a way to know which state is active, though you
|
|
will normally only need this for debugging purposes. If what you need simply
|
|
is doing something with the active state, <span class="command"><strong><a class="command" href="ar01s03.html#UML-internal-transition">internal transitions</a></strong></span> or
|
|
<span class="command"><strong><a class="command" href="ar01s04.html#backend-visitor">visitors</a></strong></span> are a better
|
|
alternative. If you need to know what state is active, const int*
|
|
current_state() will return an array of state ids. Please refer to the
|
|
<span class="command"><strong><a class="command" href="ar01s07.html#internals-state-id">internals section</a></strong></span> to
|
|
know how state ids are generated.</p></div><div class="sect4" title="Base state type"><div class="titlepage"><div><div><h5 class="title"><a name="d0e3473"></a> Base state type </h5></div></div></div><p>Sometimes, one needs to customize states to avoid repetition and provide a
|
|
common functionality, for example in the form of a virtual method. You might
|
|
also want to make your states polymorphic so that you can call typeid on
|
|
them for logging or debugging. It is also useful if you need a visitor, like
|
|
the next section will show. You will notice that all front-ends offer the
|
|
possibility of adding a base type. Not that all states and state machines
|
|
must have the same base state, so this could reduce reuse. For example,
|
|
using the basic front end, you need to:</p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>Add the non-default base state in your msm::front::state<>
|
|
definition, as first template argument (except for
|
|
interrupt_states for which it is the second argument, the first
|
|
one being the event ending the interrupt), for example,
|
|
my_base_state being your new base state for all states in a
|
|
given state machine: <code class="code">struct Empty : public
|
|
msm::front::state<my_base_state></code> Now,
|
|
my_base_state is your new base state. If it has a virtual
|
|
function, your states become polymorphic. MSM also provides a
|
|
default polymorphic base type for your convenience,
|
|
<code class="code">msm::front::polymorphic_state</code>
|
|
</p></li><li class="listitem"><p>Add the user-defined base state in the state machine frontend
|
|
definition, as a second template argument, for example:
|
|
<code class="code">struct player_ : public
|
|
msm::front::state_machine<player_,my_base_state>
|
|
</code></p></li></ul></div><p>You can also ask for a state with a given id (which you might have gotten
|
|
from current_state()) using <code class="code">const base_state* get_state_by_id(int id)
|
|
const</code> where base_state is the one you just defined. You can now
|
|
do something ploymorphically. For example using the visitor.</p></div><div class="sect4" title="Visitor"><div class="titlepage"><div><div><h5 class="title"><a name="d0e3498"></a><span class="command"><strong><a name="backend-visitor"></a></strong></span>Visitor</h5></div></div></div><p>In some cases, having a pointer-to-base of the currently active states is
|
|
not enough. You might want to call non-virtually a method of the currently
|
|
active states. It will not be said that MSM forces the virtual keyword down
|
|
your throat!</p><p>To achieve this goal, MSM provides its own variation of a visitor pattern
|
|
using the previously described user-defined state technique. If you add to
|
|
your user-defined base state an <code class="code">accept_sig</code> typedef giving the
|
|
return value (unused for the moment) and signature and provide an accept
|
|
method with this signature, calling visit_current_states will cause accept
|
|
to be called on the currently active states. Typically, you will also want
|
|
to provide an empty default accept in your base state in order in order not
|
|
to force all your states to implement accept. For example your base state
|
|
could be:</p><p><code class="code">struct my_visitable_state{</code></p><p><code class="code">// signature of the accept function</code></p><p><code class="code">typedef args<void> accept_sig;</code></p><p><code class="code">// we also want polymorphic states</code></p><p><code class="code">virtual ~my_visitable_state() {}</code></p><p><code class="code">// default implementation for states who do not need to be
|
|
visited</code></p><p><code class="code">void accept() const {}</code></p><p><code class="code">};</code></p><p>This makes your states polymorphic and visitable. In this case, accept is
|
|
made const and takes no argument. It could also be:</p><p><code class="code">struct SomeVisitor {…};</code></p><p><code class="code">struct my_visitable_state{</code></p><p><code class="code">// signature of the accept function</code></p><p><code class="code">typedef args<void,SomeVisitor&> accept_sig;</code></p><p><code class="code">// we also want polymorphic states</code></p><p><code class="code">virtual ~my_visitable_state() {}</code></p><p><code class="code">// default implementation for states who do not need to be
|
|
visited</code></p><p><code class="code">void accept(SomeVisitor&) const {}</code></p><p><code class="code">};</code></p><p>And now, accept will take one argument (it could also be non-const). By
|
|
default, accept takes up to 2 arguments. To get more, add a #define
|
|
BOOST_MSM_VISITOR_ARG_SIZE to another value before including
|
|
state_machine.hpp. For example:</p><p><code class="code">#define BOOST_MSM_VISITOR_ARG_SIZE 3</code></p><p><code class="code">#include <boost/msm/back/state_machine.hpp></code></p><p>Note that accept will be called on ALL active states <span class="underline">and also automatically on sub-states of a
|
|
submachine</span>.</p><p><span class="underline">Important warning</span>: The method
|
|
visit_current_states takes its parameter by value, so if the signature of
|
|
the accept function is to contain a parameter passed by reference, pass this
|
|
parameter with a boost:ref/cref to avoid undesired copies or slicing. So,
|
|
for example, in the above case, call:</p><p><code class="code">SomeVisitor vis; sm.visit_current_states(boost::ref(vis));
|
|
</code></p><p>This <a class="link" href="examples/SM-2Arg.cpp" target="_top">example</a> uses a
|
|
visiting function with 2 arguments.</p></div><div class="sect4" title="Flags"><div class="titlepage"><div><div><h5 class="title"><a name="d0e3587"></a>Flags</h5></div></div></div><p>Flags is a MSM-only concept, supported by all front-ends, which base
|
|
themselves on the functions: </p><p><code class="code">template <class Flag> bool is_flag_active()</code> and</p><p><code class="code">template <class Flag,class BinaryOp> bool is_flag_active()</code>
|
|
</p><p>These functions return true if the currently active state(s) support the
|
|
Flag property. The first variant ORs the result if there are several
|
|
orthogonal regions, the second one expects OR or AND, for example:</p><p><code class="code">my_fsm.is_flag_active<MyFlag>()</code></p><p><code class="code">my_fsm.is_flag_active<MyFlag,my_fsm_type::Flag_OR>()</code></p><p>Please refer to the front-ends sections for more information.</p></div><div class="sect4" title="Getting a state"><div class="titlepage"><div><div><h5 class="title"><a name="d0e3610"></a>Getting a state</h5></div></div></div><p>It is sometimes necessary to have the client code get access to the
|
|
states' data. After all, the states are created once for good and hang
|
|
around as long as the state machine does so why not use it? You simply just
|
|
need sometimes to get information about any state, even inactive ones. An
|
|
example is if you want to write a coverage tool and know how many times a
|
|
state was visited. To get a state, use the get_state method giving the state
|
|
name, for example: </p><p><code class="code">player::Stopped* tempstate =
|
|
p.get_state<player::Stopped*>();</code> or </p><p><code class="code">player::Stopped& tempstate2 =
|
|
p.get_state<player::Stopped&>();</code> depending on your
|
|
personal taste. </p></div><div class="sect4" title="State machine constructor with arguments"><div class="titlepage"><div><div><h5 class="title"><a name="d0e3623"></a> State machine constructor with arguments </h5></div></div></div><p>You might want to define a state machine with a non-default constructor.
|
|
For example, you might want to write: </p><p><code class="code">struct player_ : public msm::front::state_machine_def<player_> {
|
|
player_(int some_value){…} } </code></p><p>This is possible, using the back-end as forwarding object: </p><p><code class="code">typedef msm::back::state_machine<player_ > player; player
|
|
p(3);</code> The back-end will call the corresponding front-end
|
|
constructor upon creation.</p><p>You can pass arguments up to the value of the
|
|
BOOST_MSM_CONSTRUCTOR_ARG_SIZE macro (currently 5) arguments. Change this
|
|
value before including any header if you need to change it. </p></div></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="ar01s03.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="ar01s05.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">UML Short Guide </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> Performance / Compilers</td></tr></table></div></body></html> |