| <?xml version="1.0" encoding="UTF-8"?> |
| <?oxygen RNGSchema="http://www.oasis-open.org/docbook/xml/5.0/rng/docbook.rng" type="xml"?> |
| <book xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0"> |
| <info> |
| <title>Meta State Machine (MSM) V2.12</title> |
| <author> |
| <personname>Christophe Henry</personname> |
| <email>christophe.j.henry@googlemail.com</email> |
| </author> |
| <copyright> |
| <year>2008-2010</year> |
| <holder> |
| <phrase> Distributed under the Boost Software License, Version 1.0. (See |
| accompanying file LICENSE_1_0.txt or copy at <link |
| xlink:href="http://www.boost.org/LICENSE_1_0.txt" |
| >http://www.boost.org/LICENSE_1_0.txt</link> ) </phrase> |
| </holder> |
| </copyright> |
| </info> |
| <preface> |
| <title>Preface</title> |
| <para>MSM is a library allowing you to easily and quickly define state machines of very high |
| performance. From this point, two main questions usually quickly arise, so please allow |
| me to try answering them upfront.</para> |
| <para> |
| <itemizedlist> |
| <listitem> |
| <para>When do I need a state machine?</para> |
| <para>More often that you think. Very often, one defined a state machine |
| informally without even noticing it. For example, one declares inside a |
| class some boolean attribute, say to remember that a task has been |
| completed. Later the boolean actually needs a third value, so it becomes an |
| int. A few weeks, a second attribute is needed. Then a third. Soon, you find |
| yourself writing:</para> |
| <para><code>void incoming_data(data)</code></para> |
| <para><code>{</code></para> |
| <para><code> if (data == packet_3 && flag1 == work_done && flag2 |
| > step3)...</code></para> |
| <para><code>}</code></para> |
| <para>This starts to look like event processing (contained inside data) if some |
| stage of the object life has been achieved (but is ugly).</para> |
| <para>This could be a protocol definition and it is a common use case for state |
| machines. Another common one is a user interface. The stage of the user's |
| interaction defines if some button is active, a functionality is available, |
| etc.</para> |
| <para>But there are many more use cases if you start looking. Actually, a whole |
| model-driven development method, Executable UML |
| (http://en.wikipedia.org/wiki/Executable_UML) specifies its complete dynamic |
| behavior using state machines. Class diagram, state machine diagrams, and an |
| action language are all you absolutely need in the Executable UML |
| world.</para> |
| </listitem> |
| <listitem> |
| <para>Another state machine library? What for?</para> |
| <para>True, there are many state machine libraries. This should already be an |
| indication that if you're not using any of them, you might be missing |
| something. Why should you use this one? Unfortunately, when looking for a |
| good state machine library, you usually pretty fast hit one or several of |
| the following snags:<itemizedlist> |
| <listitem> |
| <para>speed: "state machines are slow" is usually the first |
| criticism you might hear. While it is often an excuse not to use |
| any and instead resort to dirty, hand-written implementations (I |
| mean, no, yours are not dirty of course, I'm talking about other |
| developers). MSM removes this often feeble excuse because it is |
| blazingly fast. Most hand-written implementations will be beaten |
| by MSM.</para> |
| </listitem> |
| <listitem> |
| <para>ease of use: good argument. If you used another library, you |
| are probably right. Many state machine definitions will look |
| similar to:</para> |
| <para><code>state s1 = new State; // a state</code></para> |
| <para><code>state s2 = new State; // another state</code></para> |
| <para><code>event e = new Event; // event</code></para> |
| <para><code>s1->addTransition(e,s2); // transition s1 -> |
| s2</code></para> |
| <para>The more transitions you have, the less readable it is. A long |
| time ago, there was not so much Java yet, and many electronic |
| systems were built with a state machine defined by a simple |
| transition table. You could easily see the whole structure and |
| immediately see if you forgot some transitions. Thanks to our |
| new OO techniques, this ease of use was gone. MSM gives you back |
| the transition table and reduces the noise to the |
| minimum.</para> |
| </listitem> |
| <listitem> |
| <para>expressiveness: MSM offers several front-ends and constantly |
| tries to improve state machine definition techniques. For |
| example, you can define a transition with eUML (one of MSM's |
| front-ends) as:</para> |
| <para><code>state1 == state2 + event [condition] / |
| action</code></para> |
| <para>This is not simply syntactic sugar. Such a formalized, |
| readable structure allows easy communication with domain experts |
| of a software to be constructed. Having domain experts |
| understand your code will greatly reduce the number of |
| bugs.</para> |
| </listitem> |
| <listitem> |
| <para>model-driven-development: a common difficulty of a |
| model-driven development is the complexity of making a |
| round-trip (generating code from model and then model from |
| code). This is due to the fact that if a state machine structure |
| is hard for you to read, chances are that your parsing tool will |
| also have a hard time. MSM's syntax will hopefully help tool |
| writers.</para> |
| </listitem> |
| <listitem> |
| <para>features: most developers use only 20% of the richly defined |
| UML standard. Unfortunately, these are never the same 20% for |
| all. And so, very likely, one will need something from the |
| standard which is not implemented. MSM offers a very large part |
| of the standard, with more on the way.</para> |
| </listitem> |
| </itemizedlist></para> |
| <para>Let us not wait any longer, I hope you will enjoy MSM and have fun with |
| it!</para> |
| </listitem> |
| </itemizedlist> |
| </para> |
| </preface> |
| <part> |
| <title>User' guide</title> |
| <chapter> |
| <title>Founding idea</title> |
| <para>Let's start with an example taken from the C++ Template Metaprogramming |
| book:</para> |
| <para> |
| <code>class player : public state_machine<player></code></para> |
| <para><code>{ </code></para> |
| <para><code>// The list of FSM states enum states { Empty, Open, Stopped, Playing, |
| Paused , initial_state = Empty }; </code></para> |
| <para><code>// transition actions void start_playback(play const&) { std::cout |
| << "player::start_playback\n"; } </code></para> |
| <para><code>void open_drawer(open_close const&) { std::cout << |
| "player::open_drawer\n"; } </code></para> |
| <para><code>void close_drawer(open_close const&) { std::cout << |
| "player::close_drawer\n"; } </code></para> |
| <para><code>void store_cd_info(cd_detected const&) { std::cout << |
| "player::store_cd_info\n"; } </code></para> |
| <para><code>void stop_playback(stop const&) { std::cout << |
| "player::stop_playback\n"; } </code></para> |
| <para><code>void pause_playback(pause const&) { std::cout << |
| "player::pause_playback\n"; } </code></para> |
| <para><code>void resume_playback(play const&) { std::cout << |
| "player::resume_playback\n"; } </code></para> |
| <para><code>void stop_and_open(open_close const&) { std::cout << |
| "player::stop_and_open\n"; } </code></para> |
| <para><code>friend class state_machine<player>; </code></para> |
| <para><code>typedef player p; // makes transition table cleaner </code></para> |
| <para><code>// Transition table </code></para> |
| <para><code>struct transition_table : mpl::vector11< </code></para> |
| <para><code>row < Stopped , play , Playing , &p::start_playback >, </code></para> |
| <para><code>row < Stopped , open_close , Open , &p::open_drawer >, </code></para> |
| <para><code>row < Open , open_close , Empty , &p::close_drawer >, </code></para> |
| <para><code>row < Empty , open_close , Open , &p::open_drawer >, </code></para> |
| <para><code>row < Empty , cd_detected , Stopped , &p::store_cd_info >, |
| </code></para> |
| <para><code>row < Playing , stop , Stopped , &p::stop_playback >, </code></para> |
| <para><code>row < Playing , pause , Paused , &p::pause_playback >, </code></para> |
| <para><code>row < Playing , open_close , Open , &p::stop_and_open >, |
| </code></para> |
| <para><code>row < Paused , play , Playing , &p::resume_playback >, </code></para> |
| <para><code>row < Paused , stop , Stopped , &p::stop_playback >, </code></para> |
| <para><code>row < Paused , open_close , Open , &p::stop_and_open > </code></para> |
| <para><code>> {}; </code></para> |
| <para><code>// Replaces the default no-transition response. </code></para> |
| <para><code>template <class Event> int no_transition(int state, Event const& e) { |
| std::cout << "no transition from state " << state << " on |
| event " << typeid(e).name() << std::endl; return state; } };</code> |
| </para> |
| <para><code>void test() { player p; p.process_event(open_close());...}</code></para> |
| <para>This example is the foundation for the idea driving MSM: a descriptive and |
| expressive language based on a transition table with as little syntactic noise as |
| possible, all this while offering as many features from the UML 2.0 standard as |
| possible. MSM also offers several expressive state machine definition syntaxes with |
| different trade-offs.</para> |
| </chapter> |
| <chapter> |
| <title>UML Short Guide</title> |
| <sect1> |
| <title>What are state machines?</title> |
| <para>State machines are the description of a thing's lifeline. They describe the |
| different stages of the lifeline, the events influencing it, and what it does |
| when a particular event is detected at a particular stage. They offer the |
| complete specification of the dynamic behavior of the thing.</para> |
| </sect1> |
| <sect1> |
| <title>Concepts</title> |
| <para>Thinking in terms of state machines is a bit surprising at first, so let us |
| have a quick glance at the concepts.</para> |
| <sect2> |
| <title>State machine, state, transition, event </title> |
| <para>A state machine is a concrete model describing the behavior of a system. |
| It is composed of a finite number of states and transitions.</para> |
| <para> |
| <inlinemediaobject> |
| <imageobject> |
| <imagedata fileref="images/sm.gif"/> |
| </imageobject> |
| </inlinemediaobject></para> |
| <para>A simple state has no sub states. It can have data, entry and exit |
| behaviors and deferred events. One can provide entry and exit behaviors |
| (also called actions) to states (or state machines), which are executed |
| whenever a state is entered or left, no matter how. A state can also have |
| internal transitions which cause no entry or exit behavior to be called. A |
| state can mark events as deferred. This means the event cannot be processed |
| if this state is active, but it must be retained. Next time a state not |
| deferring this event is active, the event will be processed, as if it had |
| just been fired. </para> |
| <para><inlinemediaobject> |
| <imageobject> |
| <imagedata fileref="images/state.gif"/> |
| </imageobject> |
| </inlinemediaobject></para> |
| <para>A transition is the switching between active states, triggered by an |
| event. Actions and guard conditions can be attached to the transition. The |
| action executes when the transition fires, the guard is a Boolean operation |
| executed first and which can prevent the transition from firing by returning |
| false.</para> |
| <para> |
| <inlinemediaobject> |
| <imageobject> |
| <imagedata fileref="images/transition.jpg"/> |
| </imageobject> |
| </inlinemediaobject></para> |
| <para>An initial state marks the first active state of a state machine. It has |
| no real existence and neither has the transition originating from it.</para> |
| <para> |
| <inlinemediaobject> |
| <imageobject> |
| <imagedata fileref="images/init_state.gif"/> |
| </imageobject> |
| </inlinemediaobject></para> |
| </sect2> |
| <sect2> |
| <title>Submachines, orthogonal regions, pseudostates </title> |
| <para>A composite state is a state containing a region or decomposed in two or |
| more regions. A composite state contains its own set of states and regions. </para> |
| <para>A submachine is a state machine inserted as a state in another state |
| machine. The same submachine can be inserted more than once. </para> |
| <para>Orthogonal regions are parts of a composite state or submachine, each |
| having its own set of mutually exclusive set of states and transitions. </para> |
| <para><inlinemediaobject> |
| <imageobject> |
| <imagedata fileref="images/regions.gif" width="60%" scalefit="1"/> |
| </imageobject> |
| </inlinemediaobject></para> |
| <para>UML also defines a number of pseudo states, which are considered important |
| concepts to model, but not enough to make them first-class citizens. The |
| terminate pseudo state terminates the execution of a state machine (MSM |
| handles this slightly differently. The state machine is not destroyed but no |
| further event processing occurs.). </para> |
| <para><inlinemediaobject> |
| <imageobject> |
| <imagedata fileref="images/terminate.gif"/> |
| </imageobject> |
| </inlinemediaobject></para> |
| <para>An exit point pseudo state exits a composite state or a submachine and |
| forces termination of execution in all contained regions.</para> |
| <para><inlinemediaobject> |
| <imageobject> |
| <imagedata fileref="images/exit.gif" width="60%" scalefit="1"/> |
| </imageobject> |
| </inlinemediaobject></para> |
| <para>An entry point pseudo state allows a kind of controlled entry inside a |
| composite. Precisely, it connects a transition outside the composite to a |
| transition inside the composite. An important point is that this mechanism |
| only allows a single region to be entered. In the above diagram, in region1, |
| the initial state would become active. </para> |
| <para><inlinemediaobject> |
| <imageobject> |
| <imagedata fileref="images/entry_point.gif"/> |
| </imageobject> |
| </inlinemediaobject></para> |
| <para>There are also two more ways to enter a submachine (apart the obvious and |
| more common case of a transition terminating on the submachine as shown in |
| the region case). An explicit entry means that an inside state is the target |
| of a transition. Unlike with direct entry, no tentative encapsulation is |
| made, and only one transition is executed. An explicit exit is a transition |
| from an inner state to a state outside the submachine (not supported by |
| MSM). I would not recommend using explicit entry or exit. </para> |
| <para><inlinemediaobject> |
| <imageobject> |
| <imagedata fileref="images/explicit.gif"/> |
| </imageobject> |
| </inlinemediaobject></para> |
| <para>The last entry possibility is using fork. A fork is an explicit entry into |
| one or more regions. Other regions are again activated using their initial |
| state. </para> |
| <para><inlinemediaobject> |
| <imageobject> |
| <imagedata fileref="images/fork.gif" width="70%" scalefit="1"/> |
| </imageobject> |
| </inlinemediaobject></para> |
| </sect2> |
| <sect2> |
| <title> |
| <command xml:id="uml-history"/>History </title> |
| <para>UML defines two kinds of history, shallow history and deep history. |
| Shallow history is a pseudo state representing the most recent substate of a |
| submachine. A submachine can have at most one shallow history. A transition |
| with a history pseudo state as target is equivalent to a transition with the |
| most recent substate as target. And very importantly, only one transition |
| may originate from the history. Deep history is a shallow history |
| recursively reactivating the substates of the most recent substate. It is |
| represented like the shallow history with a star (H* inside a |
| circle).</para> |
| <para> |
| <inlinemediaobject> |
| <imageobject> |
| <imagedata fileref="images/history.gif" width="60%" scalefit="1"/> |
| </imageobject> |
| </inlinemediaobject></para> |
| <para>History is not a completely satisfying concept. First of all, there can be |
| just one history pseudo state and only one transition may originate from it. |
| So they do not mix well with orthogonal regions as only one region can be |
| “remembered”. Deep history is even worse and looks like a last-minute |
| addition. History has to be activated by a transition and only one |
| transition originates from it, so how to model the transition originating |
| from the deep history pseudo state and pointing to the most recent substate |
| of the substate? As a bonus, it is also inflexible and does not accept new |
| types of histories. Let's face it, history sounds great and is useful in |
| theory, but the UML version is not quite making the cut. And therefore, MSM |
| provides a different version of this useful concept. </para> |
| </sect2> |
| <sect2> |
| <title><command xml:id="uml-anonymous"/>Completion transitions / anonymous |
| transitions</title> |
| <para>Completion events (or transitions), also called anonymous transitions, are |
| defined as transitions having no defined event triggering them. This means |
| that such transitions will immediately fire when a state being the source of |
| an anonymous transition becomes active, provided that a guard allows it. |
| They are useful in modeling algorithms as an activity diagram would normally |
| do. In the real-time world, they have the advantage of making it easier to |
| estimate how long a periodically executed action will last. For example, |
| consider the following diagram. </para> |
| <para><inlinemediaobject> |
| <imageobject> |
| <imagedata fileref="images/completion.gif"/> |
| </imageobject> |
| </inlinemediaobject></para> |
| <para>The designer now knows at any time that he will need a maximum of 4 |
| transitions. Being able to estimate how long a transition takes, he can |
| estimate how much of a time frame he will need to require (real-time tasks |
| are often executed at regular intervals). If he can also estimate the |
| duration of actions, he can even use graph algorithms to better estimate his |
| timing requirements. </para> |
| </sect2> |
| <sect2> |
| <title><command xml:id="UML-internal-transition"/> Internal transitions </title> |
| <para>Internal transitions are transitions executing in the scope of the active |
| state, being a simple state or a submachine. One can see them as a |
| self-transition of this state, without an entry or exit action |
| called.</para> |
| </sect2> |
| <sect2> |
| <title> |
| <command xml:id="transition-conflict"/>Conflicting transitions </title> |
| <para>If, for a given event, several transitions are enabled, they are said to |
| be in conflict. There are two kinds of conflicts: <itemizedlist> |
| <listitem> |
| <para>For a given source state, several transitions are defined, |
| triggered by the same event. Normally, the guard condition in |
| each transition defines which one is fired.</para> |
| </listitem> |
| <listitem> |
| <para>The source state is a submachine or simple state and the |
| conflict is between a transition internal to this state and a |
| transition triggered by the same event and having as target |
| another state.</para> |
| </listitem> |
| </itemizedlist>The first one is simple; one only needs to define two or more |
| rows in the transition table, with the same source and trigger, with a |
| different guard condition. Beware, however, that the UML standard wants |
| these conditions to be not overlapping. If they do, the standard says |
| nothing except that this is incorrect, so the implementer is free to |
| implement it the way he sees fit. In the case of MSM, the transition |
| appearing last in the transition table gets selected first, if it returns |
| false (meaning disabled), the library tries with the previous one, and so |
| on.</para> |
| <para> |
| <inlinemediaobject> |
| <imageobject> |
| <imagedata fileref="images/conflict1.gif"/> |
| </imageobject> |
| </inlinemediaobject></para> |
| <para>In the second case, UML defines that the most inner transition gets |
| selected first, which makes sense, otherwise no exit point pseudo state |
| would be possible (the inner transition brings us to the exit point, from |
| where the containing state machine can take over). </para> |
| <para><inlinemediaobject> |
| <imageobject> |
| <imagedata fileref="images/conflict2.gif" width="60%" scalefit="1"/> |
| </imageobject> |
| </inlinemediaobject></para> |
| <para>MSM handles both cases itself, so the designer needs only concentrate on |
| its state machine and the UML subtleties (not overlapping conditions), not |
| on implementing this behavior himself. </para> |
| </sect2> |
| </sect1> |
| <sect1> |
| <title>State machine glossary</title> |
| <para> |
| <itemizedlist> |
| <listitem> |
| <para>state machine: the life cycle of a thing. It is made of states, |
| regions, transitions and processes incoming events.</para> |
| </listitem> |
| <listitem> |
| <para>state: a stage in the life cycle of a state machine. A state (like |
| a submachine) can have an entry and exit behaviors.</para> |
| </listitem> |
| <listitem> |
| <para>event: an incident provoking (or not) a reaction of the state |
| machine</para> |
| </listitem> |
| <listitem> |
| <para>transition: a specification of how a state machine reacts to an |
| event. It specifies a source state, the event triggering the |
| transition, the target state (which will become the newly active |
| state if the transition is triggered), guard and actions.</para> |
| </listitem> |
| <listitem> |
| <para>action: an operation executed during the triggering of the |
| transition.</para> |
| </listitem> |
| <listitem> |
| <para>guard: a boolean operation being able to prevent the triggering of |
| a transition which would otherwise fire.</para> |
| </listitem> |
| <listitem> |
| <para>transition table: representation of a state machine. A state |
| machine diagram is a graphical, but incomplete representation of the |
| same model. A transition table, on the other hand, is a complete |
| representation.</para> |
| </listitem> |
| <listitem> |
| <para>initial state: The state in which the state machine starts. Having |
| several orthogonal regions means having as many initial |
| states.</para> |
| </listitem> |
| <listitem> |
| <para>submachine: A submachine is a state machine inserted as a state in |
| another state machine and can be found several times in a same state |
| machine.</para> |
| </listitem> |
| <listitem> |
| <para>orthogonal regions: (logical) parallel flow of execution of a |
| state machine. Every region of a state machine gets a chance to |
| process an incoming event.</para> |
| </listitem> |
| <listitem> |
| <para>terminate pseudo-state: when this state becomes active, it |
| terminates the execution of the whole state machine. MSM does not |
| destroy the state machine as required by the UML standard, however, |
| which lets you keep all the state machine's data.</para> |
| </listitem> |
| <listitem> |
| <para>entry/exit pseudo state: defined for submachines and are defined |
| as a connection between a transition outside of the submachine and a |
| transition inside the submachine. It is a way to enter or leave a |
| submachine through a predefined point.</para> |
| </listitem> |
| <listitem> |
| <para>fork: a fork allows explicit entry into several orthogonal regions |
| of a submachine.</para> |
| </listitem> |
| <listitem> |
| <para>history: a history is a way to remember the active state of a |
| submachine so that the submachine can proceed in its last active |
| state next time it becomes active.</para> |
| </listitem> |
| <listitem> |
| <para>completion events (also called completion/anonymous transitions): |
| when a transition has no named event triggering it, it automatically |
| fires when the source state is active, unless a guard forbids |
| it.</para> |
| </listitem> |
| <listitem> |
| <para>transition conflict: a conflict is present if for a given source |
| state and incoming event, several transitions are possible. UML |
| specifies that guard conditions have to solve the conflict.</para> |
| </listitem> |
| <listitem> |
| <para>internal transitions: transition from a state to itself without |
| having exit and entry actions being called.</para> |
| </listitem> |
| </itemizedlist> |
| </para> |
| </sect1> |
| </chapter> |
| <chapter> |
| <title>Tutorial</title> |
| <sect1> |
| <title>Design</title> |
| <para>MSM is divided between front–ends and back-ends. At the moment, there is just |
| one back-end. On the front-end side, you will find three of them which are as |
| many state machine description languages, with many more possible. For potential |
| language writers, this document contains a <link |
| xlink:href="#internals-front-back-interface">description of the interface |
| between front-end and back-end</link>.</para> |
| <para>The first front-end is an adaptation of the example provided in the <link |
| xlink:href="http://boostpro.com/mplbook">MPL book</link> with actions |
| defined as pointers to state or state machine methods. The second one is based |
| on functors. The third, eUML (embedded UML) is an experimental language based on |
| Boost.Proto and Boost.Typeof and hiding most of the metaprogramming to increase |
| readability. Both eUML and the functor front-end also offer a functional library |
| (a bit like Boost.Phoenix) for use as action language (UML defining |
| none).</para> |
| </sect1> |
| <sect1> |
| <title><command xml:id="basic-front-end"/>Basic front-end</title> |
| <para>This is the historical front-end, inherited from the MPL book. It provides a |
| transition table made of rows of different names and functionality. Actions and |
| guards are defined as methods and referenced through a pointer in the |
| transition. This front-end provides a simple interface making easy state |
| machines easy to define, but more complex state machines a bit harder.</para> |
| <sect2> |
| <title>A simple example</title> |
| <para>Let us have a look at a state machine diagram of the founding |
| example:</para> |
| <para><inlinemediaobject> |
| <imageobject> |
| <imagedata fileref="images/SimpleTutorial.jpg" width="60%" |
| scalefit="1"/> |
| </imageobject> |
| </inlinemediaobject></para> |
| <para>We are now going to build it with MSM's basic front-end. An <link |
| xlink:href="examples/SimpleTutorial.cpp">implementation</link> is also |
| provided.</para> |
| </sect2> |
| <sect2> |
| <title>Transition table</title> |
| <para>As previously stated, MSM is based on the transition table, so let us |
| define one:</para> |
| <programlisting> |
| struct transition_table : mpl::vector< |
| // Start Event Target Action Guard |
| // +---------+------------+-----------+---------------------------+----------------------------+ |
| a_row< Stopped , play , Playing , &player_::start_playback >, |
| a_row< Stopped , open_close , Open , &player_::open_drawer >, |
| _row< Stopped , stop , Stopped >, |
| // +---------+------------+-----------+---------------------------+----------------------------+ |
| a_row< Open , open_close , Empty , &player_::close_drawer >, |
| // +---------+------------+-----------+---------------------------+----------------------------+ |
| a_row< Empty , open_close , Open , &player_::open_drawer >, |
| row< Empty , cd_detected, Stopped , &player_::store_cd_info , &player_::good_disk_format >, |
| row< Empty , cd_detected, Playing , &player_::store_cd_info , &player_::auto_start >, |
| // +---------+------------+-----------+---------------------------+----------------------------+ |
| a_row< Playing , stop , Stopped , &player_::stop_playback >, |
| a_row< Playing , pause , Paused , &player_::pause_playback >, |
| a_row< Playing , open_close , Open , &player_::stop_and_open >, |
| // +---------+------------+-----------+---------------------------+----------------------------+ |
| a_row< Paused , end_pause , Playing , &player_::resume_playback >, |
| a_row< Paused , stop , Stopped , &player_::stop_playback >, |
| a_row< Paused , open_close , Open , &player_::stop_and_open > |
| // +---------+------------+-----------+---------------------------+----------------------------+ |
| > {}; |
| </programlisting> |
| <para>You will notice that this is almost exactly our founding example. The only |
| change in the transition table is the different types of transitions (rows). |
| The founding example forces one to define an action method and offers no |
| guards. You have 4 basic row types:<itemizedlist> |
| <listitem> |
| <para><code>row</code> takes 5 arguments: start state, event, target |
| state, action and guard.</para> |
| </listitem> |
| <listitem> |
| <para><code>a_row</code> (“a” for action) allows defining only the |
| action and omit the guard condition.</para> |
| </listitem> |
| <listitem> |
| <para><code>g_row</code> (“g” for guard) allows omitting the action |
| behavior and defining only the guard.</para> |
| </listitem> |
| <listitem> |
| <para><code>_row</code> allows omitting action and guard.</para> |
| </listitem> |
| </itemizedlist></para> |
| <para>The signature for an action methods is void method_name (event |
| const&), for example:</para> |
| <programlisting>void stop_playback(stop const&)</programlisting> |
| <para>Action methods return nothing and take the argument as const reference. Of |
| course nothing forbids you from using the same action for several |
| events:</para> |
| <programlisting>template <class Event> void stop_playback(Eventconst&)</programlisting> |
| <para>Guards have as only difference the return value, which is a |
| boolean:</para> |
| <programlisting>bool good_disk_format(cd_detected const& evt)</programlisting> |
| <para>The transition table is actually a MPL vector (or list), which brings the |
| limitation that the default maximum size of the table is 20. If you need |
| more transitions, overriding this default behavior is necessary, so you need |
| to add before any header:</para> |
| <programlisting>#define BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS |
| #define BOOST_MPL_LIMIT_VECTOR_SIZE 30 //or whatever you need |
| #define BOOST_MPL_LIMIT_MAP_SIZE 30 //or whatever you need </programlisting> |
| <para>The other limitation is that the MPL types are defined only up to 50 |
| entries. For the moment, the only solution to achieve more is to add headers |
| to the MPL (luckily, this is not very complicated).</para> |
| </sect2> |
| <sect2> |
| <title>Defining states with entry/exit actions</title> |
| <para>While states were enums in the MPL book, they now are classes, which |
| allows them to hold data, provide entry, exit behaviors and be reusable (as |
| they do not know anything about the containing state machine). To define a |
| state, inherit from the desired state type. You will mainly use simple |
| states:</para> |
| <para>struct Empty : public msm::front::state<> {};</para> |
| <para>They can optionally provide entry and exit behaviors:</para> |
| <programlisting language="C++"> |
| struct Empty : public msm::front::state<> |
| { |
| template <class Event, class Fsm> |
| void on_entry(Event const&, Fsm& ) |
| {std::cout <<"entering: Empty" << std::endl;} |
| template <class Event, class Fsm> |
| void on_exit(Event const&, Fsm& ) |
| {std::cout <<"leaving: Empty" << std::endl;} |
| }; |
| </programlisting> |
| <para>Notice how the entry and exit behaviors are templatized on the event and |
| state machine. Being generic facilitates reuse. There are more state types |
| (terminate, interrupt, pseudo states, etc.) corresponding to the UML |
| standard state types. These will be described in details in the next |
| sections.</para> |
| </sect2> |
| <sect2> |
| <title>Defining a simple state machine</title> |
| <para>Declaring a state machine is straightforward and is done with a high |
| signal / noise ratio. In our player example, we declare the state machine |
| as:</para> |
| <programlisting>struct player_ : public msm::front::state_machine_def<player_>{ |
| /* see below */}</programlisting> |
| <para>This declares a state machine using the basic front-end. We now declare |
| inside the state machine structure the initial state:</para> |
| <para> |
| <programlisting>typedef Empty initial_state;</programlisting> |
| </para> |
| <para>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 like.</para> |
| <para>All what is left to do is to pick a back-end (which is quite simple as |
| there is only one at the moment):</para> |
| <para> |
| <programlisting>typedef msm::back::state_machine<player_> player;</programlisting> |
| </para> |
| <para>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 fastest 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.</para> |
| <para>State objects are built automatically with the state machine. They will |
| exist until state machine destruction. MSM is using Boost.Fusion behind the |
| hood. This unfortunately means that if you define more than 10 states, you |
| will need to extend the default:</para> |
| <para> |
| <programlisting>#define FUSION_MAX_VECTOR_SIZE 20 // or whatever you need |
| </programlisting> |
| </para> |
| <para>When an unexpected event is fired, the <code>no_transition(event, state |
| machine, state id)</code> method of the state machine is called . By |
| default, this method simply asserts when called. It is possible to overwrite |
| the <code>no_transition</code> method to define a different handling:</para> |
| <para> |
| <programlisting>template <class Fsm,class Event> |
| void no_transition(Event const& e, Fsm& ,int state){...}</programlisting> |
| </para> |
| <para><emphasis role="underline">Note</emphasis>: you might have noticed that |
| the tutorial calls <code>start()</code> on the state machine just after |
| creation. The start method will initiate the state machine, meaning it will |
| activate the initial state, which means in turn that the initial state's |
| entry behavior will be called. The reason why we need this will be explained |
| in the <link xlink:href="#backend-start">back-end part</link>. After a call |
| to start, the state machine is ready to process events.</para> |
| </sect2> |
| <sect2> |
| <title>Defining a submachine</title> |
| <para>We now want to extend our last state machine by making the Playing state a |
| state machine itself (a submachine).</para> |
| <para><inlinemediaobject> |
| <imageobject> |
| <imagedata fileref="images/CompositeTutorial.jpg" width="60%" |
| scalefit="1"/> |
| </imageobject> |
| </inlinemediaobject></para> |
| <para>Again, an <link xlink:href="examples/CompositeTutorial.cpp">example</link> |
| is also provided.</para> |
| <para>A submachine really is a state machine itself, so we declare Playing as |
| such, choosing a front-end and a back-end:</para> |
| <para> |
| <programlisting>struct Playing_ : public msm::front::state_machine_def<Playing_>{...} |
| typedef msm::back::state_machine<Playing_> Playing;</programlisting> |
| </para> |
| <para>Like for any state machine, one also needs a transition table and an |
| initial state:</para> |
| <para> |
| <programlisting> |
| struct transition_table : mpl::vector< |
| // Start Event Target Action Guard |
| // +--------+---------+--------+---------------------------+------+ |
| a_row< Song1 , NextSong, Song2 , &Playing_::start_next_song >, |
| a_row< Song2 , NextSong, Song1 , &Playing_::start_prev_song >, |
| a_row< Song2 , NextSong, Song3 , &Playing_::start_next_song >, |
| a_row< Song3 , NextSong, Song2 , &Playing_::start_prev_song > |
| // +--------+---------+--------+---------------------------+------+ |
| > {}; |
| </programlisting> |
| </para> |
| <para> |
| <programlisting>typedef Song1 initial_state; </programlisting> |
| </para> |
| <para>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. You can even decide to use a state machine sometimes as |
| submachine or sometimes as an independent state machine.</para> |
| </sect2> |
| <sect2> |
| <title>Orthogonal regions, terminate state, event deferring</title> |
| <para>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:</para> |
| <para><inlinemediaobject> |
| <imageobject> |
| <imagedata fileref="images/error_no_regions.jpg" width="60%" |
| scalefit="1"/> |
| </imageobject> |
| </inlinemediaobject></para> |
| <para>This is neither very readable nor beautiful. And we do not even have any |
| action on the transitions yet to make it even less readable.</para> |
| <para>Luckily, UML provides a helpful concept, orthogonal regions. See them as |
| lightweight state machines running at the same time inside a common 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>no_transition</code>" will be called only if no region at |
| all handles the event. Also, as UML mandates, every region gets a chance of |
| handling the event, in the order as declared by the |
| <code>initial_state</code> type.</para> |
| <para>Adding an orthogonal region is easy, one only needs to declare more states |
| in the <code>initial_state</code> typedef. So, adding a new region with |
| AllOk as the region's initial state is:</para> |
| <para> |
| <programlisting>typedef mpl::vector<Empty,AllOk> initial_state;</programlisting> |
| </para> |
| <para><inlinemediaobject> |
| <imageobject> |
| <imagedata fileref="images/Orthogonal-deferred.jpg" width="60%" |
| scalefit="1"/> |
| </imageobject> |
| </inlinemediaobject></para> |
| <para>Furthermore, when you detect an error, you usually do not want events to |
| be further processed. 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 |
| events are ignored. This is of course not mandatory, one can use orthogonal |
| regions without terminate states. 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. </para> |
| <para><command xml:id="basic-defer"/>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.</para> |
| <para>UML defines event deferring as a state property. To accommodate this, MSM |
| lets you specify this in states by providing a <code>deferred_events</code> |
| type:</para> |
| <programlisting>struct Empty : public msm::front::state<> |
| { |
| // if the play event is fired while in this state, defer it until a state |
| // handles or rejects it |
| typedef mpl::vector<play> deferred_events; |
| ... |
| }; </programlisting> |
| <para>Please have a look at the <link |
| xlink:href="examples/Orthogonal-deferred.cpp">complete |
| example</link>.</para> |
| <para>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 for more sophisticated behaviors. It would also be conform to the MSM |
| philosophy to get as much as possible in the transition table, where you |
| have the whole state machine structure. 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>Row</code> |
| type, please have a look at the <command xlink:href="#functor-front-end" |
| >functor front-end.</command></para> |
| <para>First, as there is no state where MSM can automatically find out the usage |
| of this feature, we need to require deferred events capability explicitly, |
| by adding a type in the state machine definition:</para> |
| <programlisting>struct player_ : public msm::front::state_machine_def<player_> |
| { |
| typedef int activate_deferred_events; |
| ... |
| }; </programlisting> |
| <para>We can now defer an event in any transition of the transition table by |
| using as action the predefined <code>msm::front::Defer</code> functor, for |
| example:</para> |
| <para> |
| <programlisting>Row < Empty , play , none , Defer , none ></programlisting> |
| </para> |
| <para>This is an internal transition row(see <command |
| xlink:href="#internal-transitions">internal transitions</command>) 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 with the added power of |
| transition behavior.</para> |
| <para>The second difference is that as we now have a transition defined, this |
| transition can play in the resolution of <command |
| xlink:href="#transition-conflict">transition conflicts</command>. For |
| example, we could model an "if (condition2) move to Playing else if |
| (condition1) defer play event":</para> |
| <para> |
| <programlisting>Row < Empty , play , none , Defer , condition1 >, |
| g_row < Empty , play , Playing , &player_::condition2 ></programlisting> |
| </para> |
| <para>Please have a look at <link xlink:href="examples/Orthogonal-deferred2.cpp" |
| >this possible implementation</link>.</para> |
| </sect2> |
| <sect2> |
| <title>History</title> |
| <para>UML defines two types of history, Shallow History and Deep History. 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. 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: </para> |
| <para> |
| <programlisting>if (Event == end_pause) |
| { |
| for (int i=0;i< song number;++i) {player.process_event(NextSong()); } |
| } </programlisting> |
| </para> |
| <para>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 substate of a submachine when this submachine |
| becomes active again. The deep history does the same recursively, so if this |
| last active substate of the submachine was itself a submachine, its last |
| active substate would become active and this will continue recursively until |
| an active state is a normal state. For example, let us have a look at the |
| following UML diagram: </para> |
| <para><inlinemediaobject> |
| <imageobject> |
| <imagedata fileref="images/HistoryTutorial.jpg" width="60%" |
| scalefit="1"/> |
| </imageobject> |
| </inlinemediaobject></para> |
| <para>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).</para> |
| <para>As explained in the <command xlink:href="#uml-history">small UML |
| tutorial</command>, History is a good concept with a not completely |
| satisfying specification. MSM kept the concept but not the specification and |
| goes another way by making this a policy and you can add your own history |
| types (the <link xlink:href="#history-interface">reference</link> explains |
| what needs to be done). Furthermore, History is a backend policy. This |
| allows you to reuse the same state machine definition with different history |
| policies in different contexts.</para> |
| <para>Concretely, your frontend stays unchanged:</para> |
| <para> |
| <programlisting>struct Playing_ : public msm::front::state_machine_def<Playing_></programlisting> |
| </para> |
| <para>You then add the policy to the backend as second parameter:</para> |
| <para> |
| <programlisting>typedef msm::back::state_machine<Playing_, |
| msm::back::ShallowHistory<mpl::vector<end_pause> > > Playing;</programlisting> |
| </para> |
| <para>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 available as a policy (but could |
| be added). 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 for itself. An <link xlink:href="examples/History.cpp" |
| >example</link> is also provided.</para> |
| </sect2> |
| <sect2> |
| <title>Completion (anonymous) transitions</title> |
| <para><command xml:id="anonymous-transitions"/>The following diagram shows an |
| example making use of this feature:</para> |
| <para><inlinemediaobject> |
| <imageobject> |
| <imagedata fileref="images/Anonymous.jpg" width="60%" scalefit="1"/> |
| </imageobject> |
| </inlinemediaobject></para> |
| <para>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 much of a time frame you are to request |
| from a scheduler. </para> |
| <para>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 force |
| leaving a state. Anonymous transitions free you from this constraint.</para> |
| <para>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.</para> |
| <para>To define such a transition, use “none” as event in the transition table, |
| for example:</para> |
| <para> |
| <programlisting>row < State3 , none , State4 , &p::State3ToState4 , &p::always_true ></programlisting> |
| </para> |
| <para><link xlink:href="examples/AnonymousTutorial.cpp">An implementation</link> |
| of the state machine diagram is also provided.</para> |
| </sect2> |
| <sect2> |
| <title><command xml:id="internal-transitions"/>Internal transitions</title> |
| <para>Internal transitions are transitions executing in the scope of the active |
| state, 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.</para> |
| <para>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 |
| <command xlink:href="#run-to-completion">internals</command> ). 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:</para> |
| <para> |
| <programlisting>g_irow < Empty /*state*/,cd_detected/*event*/,&p::internal_guard/* guard */></programlisting> |
| </para> |
| <para>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 higher |
| priority for internal transitions. Please have a look at <link |
| xlink:href="examples/SimpleTutorialInternal.cpp">the |
| example</link>.</para> |
| <para>It is also possible to do it the UML-conform way by declaring a transition |
| table called <code>internal transition_table</code> inside the state itself |
| and using internal row types. For example:</para> |
| <programlisting>struct Empty : public msm::front::state<> |
| { |
| struct internal_transition_table : mpl::vector< |
| a_internal < cd_detected , Empty, &Empty::internal_action > |
| > {}; |
| };</programlisting> |
| <para>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:<itemizedlist> |
| <listitem> |
| <para>internal tables are NOT called transition_table but |
| internal_transition_table</para> |
| </listitem> |
| <listitem> |
| <para>they use different but similar row types: a_internal, |
| g_internal, _internal and internal.</para> |
| </listitem> |
| <listitem> |
| <para>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.</para> |
| </listitem> |
| <listitem> |
| <para>This also allows you, if you wish, to use actions and guards |
| from another state of the state machine or in the state machine |
| itself.</para> |
| </listitem> |
| <listitem> |
| <para>submachines can have an internal transition table and a |
| classical transition table.</para> |
| </listitem> |
| </itemizedlist></para> |
| <para>The <link xlink:href="examples/TestInternal.cpp">following example</link> |
| makes use of an a_internal. It also uses functor-based internal transitions |
| which will be explained in <command |
| xlink:href="#functor-internal-transitions">the functor |
| front-end</command>, please ignore them for the moment. Also note that |
| the state-defined internal transitions, having the highest priority (as |
| mandated by the UML standard), are tried before those defined inside the |
| state machine transition table.</para> |
| <para>Which method should you use? It depends on what you need:<itemizedlist> |
| <listitem> |
| <para>the first version (using irow) is simpler and likely to |
| compile faster. It also lets you choose the priority of your |
| internal transition.</para> |
| </listitem> |
| <listitem> |
| <para>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.</para> |
| </listitem> |
| </itemizedlist> |
| <command xml:id="internal-transitions-note"/><emphasis role="underline" |
| ><emphasis role="bold">Note</emphasis></emphasis>: There is an added |
| possibility coming from this feature. The |
| <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 to the state machine itself the only task of |
| declaring the states it wants to use using the |
| <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 show this possibility:<itemizedlist> |
| <listitem> |
| <para><link |
| xlink:href="examples/distributed_table/DistributedTable.cpp" |
| >state machine definition</link></para> |
| </listitem> |
| <listitem> |
| <para>Empty <link xlink:href="examples/distributed_table/Empty.hpp" |
| >header</link> and <link |
| xlink:href="examples/distributed_table/Empty.cpp" |
| >cpp</link></para> |
| </listitem> |
| <listitem> |
| <para>Open <link xlink:href="examples/distributed_table/Open.hpp" |
| >header</link> and <link |
| xlink:href="examples/distributed_table/Open.cpp" |
| >cpp</link></para> |
| </listitem> |
| <listitem> |
| <para><link xlink:href="examples/distributed_table/Events.hpp" |
| >events definition</link></para> |
| </listitem> |
| </itemizedlist></para> |
| <para>There is an added bonus offered for submachines, which can have both the |
| standard transition_table and an internal_transition_table (which has a |
| 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 any front-end.</para> |
| </sect2> |
| <sect2> |
| <title><command xml:id="basic-row2"/>more row types</title> |
| <para>It is also possible to write transitions using actions and guards 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>row2</code>. |
| They come, like normal transitions in four flavors: <code>a_row2, g_row2, |
| _row2 and row2</code>. For example, a transition calling an action from |
| the state Empty could be:</para> |
| <para> |
| <programlisting>a_row2<Stopped,open_close,Open,Empty |
| /*action source*/,&Empty::open_drawer/*action*/></programlisting> |
| </para> |
| <para>The same capabilities are also available for internal transitions so that |
| we have: <code>a_irow2, g_irow2, _irow2 and row2</code>. For transitions |
| defined as part of the <code>internal_transition_table</code>, you can use |
| the <command xlink:href="#internal-transitions">a_internal, g_internal, |
| _internal, internal</command> row types from the previous |
| sections.</para> |
| <para>These row types allow us to distribute the state machine code among |
| states, making them reusable and more useful. Using transition tables inside |
| states also contributes to this possibility. An <link |
| xlink:href="examples/SimpleTutorial2.cpp">example</link> of these new |
| rows is also provided.</para> |
| </sect2> |
| <sect2> |
| <title>Explicit entry / entry and exit pseudo-state / fork</title> |
| <para>MSM (almost) fully supports these features, described in the <command |
| xlink:href="#uml-history">small UML tutorial</command>. Almost because |
| there are currently two limitations: <itemizedlist> |
| <listitem> |
| <para>it is only possible to explicitly enter a sub- state of the |
| target but not a sub-sub state.</para> |
| </listitem> |
| <listitem> |
| <para>it is not possible to explicitly exit. Exit points must be |
| used.</para> |
| </listitem> |
| </itemizedlist></para> |
| <para>Let us see a concrete example:</para> |
| <para><inlinemediaobject> |
| <imageobject> |
| <imagedata fileref="images/entrytutorial.jpg" width="60%" |
| scalefit="1"/> |
| </imageobject> |
| </inlinemediaobject></para> |
| <para>We find in this diagram:<itemizedlist> |
| <listitem> |
| <para>A “normal” activation of SubFsm2, triggered by event1. In each |
| region, the initial state is activated, i.e. SubState1 and |
| SubState1b.</para> |
| </listitem> |
| <listitem> |
| <para>An explicit entry into SubFsm2::SubState2 for region “1” with |
| event2 as trigger, meaning that in region “2” the initial state, |
| SubState1b, activated.</para> |
| </listitem> |
| <listitem> |
| <para>A fork into regions “1” and “2” to the explicit entries |
| SubState2 and SubState2b, triggered by event3. Both states |
| become active so no region is default activated (if we had a |
| third one, it would be).</para> |
| </listitem> |
| <listitem> |
| <para>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). Region “2” is default-activated |
| and SubState1b becomes active.</para> |
| </listitem> |
| <listitem> |
| <para>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.</para> |
| </listitem> |
| </itemizedlist></para> |
| <para>The example is also <link xlink:href="examples/DirectEntryTutorial.cpp" |
| >fully implemented</link>.</para> |
| <para>This sounds complicated but the syntax is simple.</para> |
| <sect3> |
| <title>Explicit entry</title> |
| <para>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 |
| region id (the region id starts with 0 and corresponds to the first |
| initial state of the initial_state type sequence).</para> |
| <para> |
| <programlisting>struct SubFsm2_ : public msm::front::state_machine_def<SubFsm2_> |
| { |
| struct SubState2 : public msm::front::state<> , |
| public msm::front::explicit_entry<0> |
| {...}; |
| ... |
| };</programlisting> |
| </para> |
| <para>And define the submachine as:</para> |
| <para> |
| <programlisting>typedef msm::back::state_machine<SubFsm2_> SubFsm2;</programlisting> |
| </para> |
| <para>You can then use it as target in a transition with State1 as |
| source:</para> |
| <para> |
| <programlisting>_row < State1, Event2, SubFsm2::direct< SubFsm2_::SubState2> > //SubFsm2_::SubState2: complete name of SubState2 (defined within SubFsm2_)</programlisting> |
| </para> |
| <para>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 an explicit |
| entry is desired.</para> |
| <para><emphasis role="underline">Note (also valid for forks)</emphasis>: 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:</para> |
| <para> |
| <programlisting>typedef mpl::vector<SubState2,SubState2b> explicit_creation;</programlisting> |
| </para> |
| <para><emphasis role="underline">Note (also valid for forks)</emphasis>: At |
| the moment, it is not possible to use a submachine as the target of an |
| explicit entry. Please use entry pseudo states for an almost identical |
| effect.</para> |
| </sect3> |
| <sect3> |
| <title>Fork</title> |
| <para>Need a fork instead of an explicit entry? 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:</para> |
| <para> |
| <programlisting>_row < State1, Event3, |
| mpl::vector<SubFsm2::direct<SubFsm2_::SubState2>, |
| SubFsm2::direct <SubFsm2_::SubState2b> |
| ></programlisting> |
| </para> |
| <para>With SubState2 defined as before and SubState2b defined as being in |
| the second region (Caution: MSM does not check that the region is |
| correct):</para> |
| <para> |
| <programlisting>struct SubState2b : public msm::front::state<> , |
| public msm::front::explicit_entry<1></programlisting> |
| </para> |
| </sect3> |
| <sect3> |
| <title>Entry pseudo states</title> |
| <para> To define an entry pseudo state, you need derive from the |
| corresponding class and give the region id:</para> |
| <para> |
| <programlisting>struct PseudoEntry1 : public msm::front::entry_pseudo_state<0></programlisting> |
| </para> |
| <para>And add the corresponding transition in the top-level state machine's |
| transition table:</para> |
| <para> |
| <programlisting>_row < State1, Event4, SubFsm2::entry_pt<SubFsm2_::PseudoEntry1> ></programlisting> |
| </para> |
| <para>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:</para> |
| <para> |
| <programlisting>_row < PseudoEntry1, Event4, SubState3,&SubFsm2_::entry_action ></programlisting> |
| </para> |
| </sect3> |
| <sect3> |
| <title> Exit pseudo states </title> |
| <para>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):</para> |
| <para> |
| <programlisting>struct PseudoExit1 : public exit_pseudo_state<event6></programlisting> |
| </para> |
| <para>And you need, like for entry pseudo states, two transitions, one in |
| the submachine:</para> |
| <para> |
| <programlisting>_row < SubState3, Event5, PseudoExit1 ></programlisting> |
| </para> |
| <para>And one in the containing state machine:</para> |
| <para> |
| <programlisting>_row < SubFsm2::exit_pt<SubFsm2_::PseudoExit1>, Event6,State2 ></programlisting> |
| </para> |
| <para><emphasis role="underline">Important note 1:</emphasis> 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.</para> |
| <para><emphasis role="underline">Important note 2</emphasis>: 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”.</para> |
| <para><emphasis role="underline">Important note 3:</emphasis> 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:</para> |
| <para> |
| <programlisting>struct event6 |
| { |
| event6(){} |
| template <class Event> |
| event6(Event const&){} |
| }; //convertible from any event</programlisting> |
| </para> |
| </sect3> |
| </sect2> |
| <sect2> |
| <title>Flags</title> |
| <para>This <link xlink:href="examples/Flags.cpp">tutorial</link> 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.</para> |
| <para>If you look into the Boost.Statechart documentation you'll find this |
| code:</para> |
| <programlisting>if ( ( state_downcast< const NumLockOff * >() != 0 ) && |
| ( state_downcast< const CapsLockOff * >() != 0 ) && |
| ( state_downcast< const ScrollLockOff * >() != 0 ) ) |
| </programlisting> |
| <para>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.</para> |
| <para>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.</para> |
| <para>In our player example, let's say we need to know if the player has a |
| loaded CD. We could do the same:</para> |
| <programlisting>if ( ( state_downcast< const Stopped * >() != 0 ) && |
| ( state_downcast< const Open * >() != 0 ) && |
| ( state_downcast< const Paused * >() != 0 ) && |
| ( state_downcast< const Playing * >() != 0 )) </programlisting> |
| <para>Or flag these 4 states as CDLoaded-able. You add a flag_list type into |
| each flagged state:</para> |
| <para> |
| <programlisting>typedef mpl::vector1<CDLoaded> flag_list;</programlisting> |
| </para> |
| <para>You can even define a list of flags, for example in Playing:</para> |
| <para> |
| <programlisting>typedef mpl::vector2<PlayingPaused,CDLoaded> flag_list;</programlisting> |
| </para> |
| <para>This means that Playing supports both properties. To check if your player |
| has a loaded CD, check if your flag is active in the current state:</para> |
| <para> |
| <programlisting>player p; if (p.is_flag_active<CDLoaded>()) ... </programlisting> |
| </para> |
| <para>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:</para> |
| <para> |
| <programlisting>if (p.is_flag_active<CDLoaded,player::Flag_AND>()) ...</programlisting> |
| </para> |
| <para>The following diagram displays the flag situation in the tutorial.</para> |
| <para><inlinemediaobject> |
| <imageobject> |
| <imagedata fileref="images/FlagsTutorial.jpg" width="60%" |
| scalefit="1"/> |
| </imageobject> |
| </inlinemediaobject></para> |
| </sect2> |
| <sect2> |
| <title><command xml:id="event-hierarchy"/>Event Hierarchy</title> |
| <para>There are cases where one needs transitions based on categories of events. |
| An example is text parsing. Let's say you want to parse a string and use a |
| state machine to manage your parsing state. You want to parse 4 digits and |
| decide to use a state for every matched digit. Your state machine could look |
| like:</para> |
| <para><inlinemediaobject> |
| <imageobject> |
| <imagedata fileref="images/ParsingDigits.jpg" width="30%" |
| scalefit="1"/> |
| </imageobject> |
| </inlinemediaobject></para> |
| <para>But how to detect the digit event? We would like to avoid defining 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: </para> |
| <programlisting>struct digit {}; |
| struct char_0 : public digit {}; </programlisting> |
| <para>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.</para> |
| <para>An <link xlink:href="examples/ParsingDigits.cpp">example</link> with |
| performance measurement, taken from the documentation of Boost.Xpressive |
| illustrates this example. You might notice that the performance is actually |
| very good (in this case even better).</para> |
| </sect2> |
| <sect2> |
| <title>Customizing a state machine / Getting more speed</title> |
| <para>MSM is offering many UML features at a high-speed, but sometimes, you just |
| need more speed and are ready to give up some features in exchange. A |
| process_event is handling several tasks: <itemizedlist> |
| <listitem> |
| <para>checking for terminate/interrupt states</para> |
| </listitem> |
| <listitem> |
| <para>handling the message queue (for entry/exit/transition actions |
| generating themselves events)</para> |
| </listitem> |
| <listitem> |
| <para>handling deferred events</para> |
| </listitem> |
| <listitem> |
| <para>catching exceptions (or not)</para> |
| </listitem> |
| <listitem> |
| <para>handling the state switching and action calls</para> |
| </listitem> |
| </itemizedlist>Of these tasks, only the last one is absolutely necessary to |
| a state machine (its core job), the other ones are nice-to-haves which cost |
| CPU time. In many cases, it is not so important, but in embedded systems, |
| this can lead to ad-hoc state machine implementations. MSM detects by itself |
| if a concrete state machine makes use of terminate/interrupt states and |
| deferred events and deactivates them if not used. For the other two, if you |
| do not need them, you need to help by indicating it in your implementation. |
| This is done with two simple typedefs:<itemizedlist> |
| <listitem> |
| <para><code>no_exception_thrown</code> indicates that behaviors will |
| never throw and MSM does not need to catch anything</para> |
| </listitem> |
| <listitem> |
| <para><code>no_message_queue</code> indicates that no action will |
| itself generate a new event and MSM can save us the message |
| queue.</para> |
| </listitem> |
| </itemizedlist>The third configuration possibility, explained <link |
| xlink:href="#basic-defer">here</link>, is to manually activate deferred |
| events, using <code>activate_deferred_events</code>. For example, the |
| following state machine sets all three configuration types:</para> |
| <programlisting>struct player_ : public msm::front::state_machine_def<player_> |
| { |
| // no need for exception handling or message queue |
| typedef int no_exception_thrown; |
| typedef int no_message_queue; |
| // also manually enable deferred events |
| typedef int activate_deferred_events |
| ...// rest of implementation |
| };</programlisting> |
| <para><emphasis role="underline">Important note</emphasis>: As exit pseudo |
| states are using the message queue to forward events out of a submachine, |
| the <code>no_message_queue</code> option cannot be used with state machines |
| containing an exit pseudo state.</para> |
| </sect2> |
| <sect2> |
| <title>Choosing the initial event</title> |
| <para>A state machine is started using the <code>start</code> method. This |
| causes the initial state's entry behavior to be executed. Like every entry |
| behavior, it becomes as parameter the event causing the state to be entered. |
| But when the machine starts, there was no event triggered. In this case, MSM |
| sends <code>msm::back::state_machine<...>::InitEvent</code>, which might |
| not be the default you'd want. For this special case, MSM provides a |
| configuration mechanism in the form of a typedef. If the state machine's |
| front-end definition provides an initial_event typedef set to another event, |
| this event will be used. For example:</para> |
| <programlisting>struct my_initial_event{}; |
| struct player_ : public msm::front::state_machine_def<player_>{ |
| ... |
| typedef my_initial_event initial_event; |
| };</programlisting> |
| </sect2> |
| <sect2> |
| <title> Containing state machine (deprecated)</title> |
| <para>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.</para> |
| <para>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 for 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:</para> |
| <programlisting>struct Stopped : public msm::front::state<sm_ptr></programlisting> |
| <para>And to provide a set_sm_ptr function: <code>void set_sm_ptr(player* |
| pl)</code></para> |
| <para>to get a pointer to the containing state machine. The same applies to |
| terminate_state / interrupt_state and entry_pseudo_state / |
| exit_pseudo_state. </para> |
| </sect2> |
| </sect1> |
| <sect1> |
| <title><command xml:id="functor-front-end"/>Functor front-end</title> |
| <para>The functor front-end is the preferred front-end at the moment. It is more |
| powerful than the standard front-end and has a more readable transition table. |
| It also makes it easier to reuse parts of state machines. Like <command |
| xlink:href="#eUML-front-end">eUML</command>, it 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.</para> |
| <para>The rows which MSM offered in the previous front-end 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: <itemizedlist> |
| <listitem> |
| <para>They are more typing and information than we would wish. This |
| means syntactic noise and more to learn.</para> |
| </listitem> |
| <listitem> |
| <para>Function pointers are weird in C++.</para> |
| </listitem> |
| <listitem> |
| <para>The action/guard signature is limited and does not allow for more |
| variations of parameters (source state, target state, current state |
| machine, etc.)</para> |
| </listitem> |
| <listitem> |
| <para>It is not easy to reuse action code from a state machine to |
| another.</para> |
| </listitem> |
| </itemizedlist></para> |
| <sect2> |
| <title> Transition table </title> |
| <para>We can change the definition of the simple tutorial's transition table |
| to:</para> |
| <programlisting> |
| struct transition_table : mpl::vector< |
| // Start Event Target Action Guard |
| // +---------+------------+-----------+---------------------------+----------------------------+ |
| Row < Stopped , play , Playing , start_playback , none >, |
| Row < Stopped , open_close , Open , open_drawer , none >, |
| Row < Stopped , stop , Stopped , none , none >, |
| // +---------+------------+-----------+---------------------------+----------------------------+ |
| Row < Open , open_close , Empty , close_drawer , none >, |
| // +---------+------------+-----------+---------------------------+----------------------------+ |
| Row < Empty , open_close , Open , open_drawer , none >, |
| Row < Empty , cd_detected, Stopped , store_cd_info , good_disk_format >, |
| g_row< Empty , cd_detected, Playing , &player_::store_cd_info , &player_::auto_start >, |
| // +---------+------------+-----------+---------------------------+----------------------------+ |
| Row < Playing , stop , Stopped , stop_playback , none >, |
| Row < Playing , pause , Paused , pause_playback , none >, |
| Row < Playing , open_close , Open , stop_and_open , none >, |
| // +---------+------------+-----------+---------------------------+----------------------------+ |
| Row < Paused , end_pause , Playing , resume_playback , none >, |
| Row < Paused , stop , Stopped , stop_playback , none >, |
| Row < Paused , open_close , Open , stop_and_open , none > |
| // +---------+------------+-----------+---------------------------+----------------------------+ |
| > {}; |
| </programlisting> |
| <para>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:</para> |
| <programlisting>struct store_cd_info |
| { |
| template <class Fsm,class Evt,class SourceState,class TargetState> |
| void operator()(Evt const&, Fsm& fsm, SourceState&,TargetState& ) |
| { |
| cout << "player::store_cd_info" << endl; |
| fsm.process_event(play()); |
| } |
| }; </programlisting> |
| <para>The advantage of functors compared to functions are that functors 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.</para> |
| <para>It is also possible to mix rows from different front-ends. To show this, a |
| g_row has been left in the transition table. <emphasis role="underline" |
| >Note:</emphasis> 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.</para> |
| <para>To illustrate the reusable point, MSM comes with a whole set of predefined |
| functors. Please refer to eUML for the <link xlink:href="#Reference-begin" |
| >full list</link>. For example, we are now going to replace the first |
| action by an action sequence and the guard by a more complex functor.</para> |
| <para>We decide we now want to execute two actions in the first transition |
| (Stopped -> Playing). We only need to change the action start_playback to |
| <programlisting>ActionSequence_< mpl::vector<some_action, start_playback> ></programlisting>and |
| now will execute some_action and start_playback every time the transition is |
| taken. ActionSequence_ is a functor calling each action of the mpl::vector |
| in sequence.</para> |
| <para>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: |
| <programlisting>And_<good_disk_format,Or_< some_condition , some_other_condition> ></programlisting>It |
| even starts looking like functional programming. MSM ships with functors for |
| operators, state machine usage, STL algorithms or container methods.</para> |
| </sect2> |
| <sect2> |
| <title>Defining states with entry/exit actions</title> |
| <para>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 <link xlink:href="examples/SimpleWithFunctors.cpp">tutorial</link>, |
| adapted from the earlier example does just this.</para> |
| <para>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:</para> |
| <programlisting>struct Empty_Entry |
| { |
| template <class Event,class Fsm,class State> |
| void operator()(Event const&,Fsm&,State&) |
| { |
| ... |
| } |
| }; // same for Empty_Exit |
| struct Empty : public msm::front::euml::func_state<Empty_Entry,Empty_Exit>{};</programlisting> |
| <para>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 <link xlink:href="examples/SimpleWithFunctors2.cpp">be |
| rewritten</link>.</para> |
| <para>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 or is a fan of functional |
| programming.</para> |
| </sect2> |
| <sect2> |
| <title>Defining a simple state machine</title> |
| <para>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 |
| <link xlink:href="examples/SimpleWithFunctors2.cpp">this |
| example</link>.</para> |
| </sect2> |
| <sect2> |
| <title>Anonymous transitions</title> |
| <para>Anonymous (completion) transitions are transitions without a named event. |
| We saw how this front-end uses <code>none</code> when no action or guard is |
| required. We can also use <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:</para> |
| <programlisting>Row < State1 , none , State2 ></programlisting> |
| <para>The following transition does the same but calling an action in the |
| process:</para> |
| <programlisting>Row < State1 , none , State2 , State1ToState2, none ></programlisting> |
| <para>The following diagram shows an example and its <link |
| xlink:href="examples/AnonymousTutorialWithFunctors.cpp" |
| >implementation</link>:</para> |
| <para><inlinemediaobject> |
| <imageobject> |
| <imagedata fileref="images/Anonymous.jpg" width="70%" scalefit="1"/> |
| </imageobject> |
| </inlinemediaobject></para> |
| </sect2> |
| <sect2> |
| <title><command xml:id="functor-internal-transitions"/>Internal |
| transitions</title> |
| <para>The <link xlink:href="examples/SimpleTutorialInternalFunctors.cpp" |
| >following example</link> uses internal transitions with the functor |
| front-end. As for the simple standard front-end, both methods of defining |
| internal transitions are supported:<itemizedlist> |
| <listitem> |
| <para>providing a <code>Row</code> in the state machine's transition |
| table with <code>none</code> as target state defines an internal |
| transition.</para> |
| </listitem> |
| <listitem> |
| <para>providing an <code>internal_transition_table</code> made of |
| <code>Internal</code> rows inside a state or submachine |
| defines UML-conform internal transitions with higher |
| priority.</para> |
| </listitem> |
| <listitem> |
| <para>transitions defined inside |
| <code>internal_transition_table</code> require no source or |
| target state as the source state is known (<code>Internal</code> |
| really are <code>Row</code> without a source or target state) |
| .</para> |
| </listitem> |
| </itemizedlist>Like for the <command xlink:href="#internal-transitions-note" |
| >standard front-end internal transitions</command>, internal transition |
| tables are added into the main state machine's table, thus allowing you to |
| distribute the transition table definition and reuse states.</para> |
| <para>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 later. 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.</para> |
| </sect2> |
| </sect1> |
| <sect1> |
| <title><command xml:id="eUML-front-end"/>eUML (experimental)</title> |
| <para><emphasis role="underline">Important note</emphasis>: eUML requires a compiler |
| supporting Boost.Typeof. More generally, eUML has experimental status because |
| most compilers will start crashing when a state machine becomes too big.</para> |
| <para>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. If it were functional |
| programming, it would be even better. This is what eUML is for.</para> |
| <para>eUML is a Boost.Proto and Boost.Typeof-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. There are grammars for actions, guards, flags, attributes, deferred |
| events, initial states.</para> |
| <para>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).</para> |
| <para>Examples will be provided in the next paragraphs. You need to include eUML |
| basic features: </para> |
| <para> |
| <programlisting>#include <msm/front/euml/euml.hpp></programlisting> |
| </para> |
| <para>To add STL support (at possible cost of longer compilation times), include: </para> |
| <para> |
| <programlisting>#include <msm/front/euml/stl.hpp></programlisting> |
| </para> |
| <para>eUML is defined in the namespace <code>msm::front::euml</code>.</para> |
| <sect2> |
| <title>Transition table</title> |
| <para>A transition can be defined using eUML as: </para> |
| <para> |
| <programlisting>source + event [guard] / action == target</programlisting> |
| </para> |
| <para>or as</para> |
| <para> |
| <programlisting>target == source + event [guard] / action</programlisting> |
| </para> |
| <para>The first version looks like a drawn transition in a diagram, the second |
| one seems natural to a C++ developer.</para> |
| <para>The simple transition table written with the <command |
| xlink:href="#functor-front-end">functor front-end</command> can now be |
| written as:</para> |
| <programlisting>BOOST_MSM_EUML_TRANSITION_TABLE(( |
| Stopped + play [some_guard] / (some_action , start_playback) == Playing , |
| Stopped + open_close/ open_drawer == Open , |
| Stopped + stop == Stopped , |
| Open + open_close / close_drawer == Empty , |
| Empty + open_close / open_drawer == Open , |
| Empty + cd_detected [good_disk_format] / store_cd_info == Stopped |
| ),transition_table) </programlisting> |
| <para>Or, using the alternative notation, it can be:</para> |
| <programlisting>BOOST_MSM_EUML_TRANSITION_TABLE(( |
| Playing == Stopped + play [some_guard] / (some_action , start_playback) , |
| Open == Stopped + open_close/ open_drawer , |
| Stopped == Stopped + stop , |
| Empty == Open + open_close / close_drawer , |
| Open == Empty + open_close / open_drawer , |
| Stopped == Empty + cd_detected [good_disk_format] / store_cd_info |
| ),transition_table) </programlisting> |
| <para>The transition table now looks like a list of (readable) rules with little |
| noise.</para> |
| <para>UML defines guards between “[ ]” and actions after a “/”, so the chosen |
| syntax 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.</para> |
| <para>If this seems to you like it will cost you run-time performance, don't |
| worry, eUML is based on typeof (decltype) which only evaluates the |
| parameters to BOOST_MSM_EUML_TRANSITION_TABLE 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-introduced |
| <command xlink:href="#functor-front-end">functor |
| front-end</command>.</para> |
| <para>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 any syntactic noise at all.</para> |
| </sect2> |
| <sect2> |
| <title>Defining events, actions and states with entry/exit actions</title> |
| <sect3> |
| <title>Events</title> |
| <para>Events must be proto-enabled. To achieve this, they must inherit from |
| a proto terminal (euml_event<event-name>). eUML also provides a macro |
| to make this easier:</para> |
| <para> |
| <programlisting>BOOST_MSM_EUML_EVENT(play)</programlisting> |
| </para> |
| <para>This declares an event type and an instance of this type called |
| <code>play</code>, which is now ready to use in state or transition |
| behaviors.</para> |
| <para>There is a second macro, BOOST_MSM_EUML_EVENT_WITH_ATTRIBUTES, which |
| takes as second parameter the attributes an event will contain, using |
| the <command xlink:href="#eUML-attributes">attribute |
| syntax</command>.</para> |
| <para><emphasis role="underline">Note</emphasis>: as we now have events |
| defined as instances instead of just types, can we still process an |
| event by creating one on the fly, like: |
| <code>fsm.process_event(play());</code> or do we have to write: |
| <code>fsm.process_event(play);</code></para> |
| <para>The answer is you can do both. The second one is easier but unlike |
| other front-ends, the second uses a defined operator(), which creates an |
| event on the fly.</para> |
| </sect3> |
| <sect3> |
| <title>Actions</title> |
| <para>Actions (returning void) and guards (returning a bool) are defined |
| like previous functors, with the difference that they also must be |
| proto-enabled. This can be done by inheriting from euml_action< |
| functor-name >. eUML also provides a macro:</para> |
| <programlisting>BOOST_MSM_EUML_ACTION(some_condition) |
| { |
| template <class Fsm,class Evt,class SourceState,class TargetState> |
| bool operator()(Evt const& ,Fsm& ,SourceState&,TargetState& ) |
| { return true; } |
| }; </programlisting> |
| <para>Like for events, this macro declares a functor type and an instance |
| for use in transition or state behaviors.</para> |
| <para>It is possible to use the same action grammar from the transition |
| table to define state entry and exit behaviors. So |
| <code>(action1,action2)</code> is a valid entry or exit behavior |
| executing both actions in turn.</para> |
| <para>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:</para> |
| <programlisting>BOOST_MSM_EUML_ACTION(Empty_Entry) |
| { |
| template <class Evt,class Fsm,class State> |
| void operator()(Evt const& ,Fsm& ,State& ) { ... } |
| }; </programlisting> |
| <para><command xml:id="eUML-reuse-functor"/>It is also possible to reuse the functors from the functor front-end. |
| The syntax is however slightly less comfortable as we need to pretend |
| creating one on the fly for typeof. For example:</para> |
| <programlisting>struct start_playback |
| { |
| template <class Fsm,class Evt,class SourceState,class TargetState> |
| void operator()(Evt const& ,Fsm&,SourceState& ,TargetState& ) |
| { |
| ... |
| } |
| }; |
| BOOST_MSM_EUML_TRANSITION_TABLE(( |
| Playing == Stopped + play / start_playback() , |
| ... |
| ),transition_table)</programlisting> |
| </sect3> |
| <sect3> |
| <title>States</title> |
| <para>There is also a macro for states. This macro has 2 arguments, first |
| the expression defining the state, then the state (instance) |
| name:</para> |
| <programlisting>BOOST_MSM_EUML_STATE((),Paused)</programlisting> |
| <para>This defines a simple state without entry or exit action. You can |
| provide in the expression parameter the state behaviors (entry and exit) |
| using the action grammar, like in the transition table:</para> |
| <programlisting>BOOST_MSM_EUML_STATE(((Empty_Entry,Dummy_Entry)/*2 entryactions*/, |
| Empty_Exit/*1 exit action*/ ), |
| Empty)</programlisting> |
| <para>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.</para> |
| <para>There are several possibilitites for the <command |
| xml:id="eUML-build-state"/> expression syntax:<itemizedlist> |
| <listitem> |
| <para>(): state without entry or exit action.</para> |
| </listitem> |
| <listitem> |
| <para>(Expr1): state with entry but no exit action.</para> |
| </listitem> |
| <listitem> |
| <para>(Expr1,Expr2): state with entry and exit action.</para> |
| </listitem> |
| <listitem> |
| <para>(Expr1,Expr2,Attributes): state with entry and exit |
| action, defining some attributes (read further on).</para> |
| </listitem> |
| <listitem> |
| <para>(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).</para> |
| </listitem> |
| <listitem> |
| <para>(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).</para> |
| </listitem> |
| </itemizedlist></para> |
| <para>no_action 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).</para> |
| <para>The BOOST_MSM_EUML_STATE macro will allow you to define most common |
| states, but sometimes you will need more, for example provide in your |
| states some special behavior. In this case, you will have to do the |
| macro's job by hand, which is not very complicated. The state will need |
| to inherit from <code>msm::front::state<></code>, like any state, and |
| from <code>euml_state<state-name></code> to be proto-enabled. You |
| will then need to declare an instance for use in the transition table. |
| For example:</para> |
| <programlisting>struct Empty_impl : public msm::front::state<> , public euml_state<Empty_impl> |
| { |
| void activate_empty() {std::cout << "switching to Empty " << std::endl;} |
| template <class Event,class Fsm> |
| void on_entry(Event const& evt,Fsm&fsm){...} |
| template <class Event,class Fsm> |
| void on_exit(Event const& evt,Fsm&fsm){...} |
| }; |
| //instance for use in the transition table |
| Empty_impl const Empty;</programlisting> |
| <para>Notice also that we defined a method named activate_empty. We would |
| like to call it inside a behavior. This can be done using the |
| BOOST_MSM_EUML_METHOD macro. </para> |
| <programlisting>BOOST_MSM_EUML_METHOD(ActivateEmpty_,activate_empty,activate_empty_,void,void)</programlisting> |
| <para>The first parameter is the name of the underlying functor, which you |
| could use with the functor front-end, the second is the state method |
| name, the third is the eUML-generated function, the fourth and fifth the |
| return value when used inside a transition or a state behavior. You can |
| now use this inside a transition:</para> |
| <programlisting>Empty == Open + open_close / (close_drawer,activate_empty_(target_))</programlisting> |
| </sect3> |
| </sect2> |
| <sect2> |
| <title>Defining a simple state machine</title> |
| <para>You can reuse the state machine definition method from the standard |
| front-end and simply replace the transition table by this new one. 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 macro, <command xml:id="eUML-build-sm" |
| />BOOST_MSM_EUML_DECLARE_STATE_MACHINE, which has 2 arguments, an expression |
| describing the state machine and the state machine name. The expression has |
| up to 8 arguments:<itemizedlist> |
| <listitem> |
| <para>(Stt, Init): simplest state machine where only the transition |
| table and initial state(s) are defined.</para> |
| </listitem> |
| <listitem> |
| <para>(Stt, Init, Expr1): state machine where the transition table, |
| initial state and entry action are defined.</para> |
| </listitem> |
| <listitem> |
| <para>(Stt, Init, Expr1, Expr2): state machine where the transition |
| table, initial state, entry and exit actions are defined.</para> |
| </listitem> |
| <listitem> |
| <para>(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).</para> |
| </listitem> |
| <listitem> |
| <para>(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 <link |
| xlink:href="#eUML-Configuration">configuration |
| capabilities</link> (no message queue / no exception |
| catching) are added.</para> |
| </listitem> |
| <listitem> |
| <para>(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 the <link |
| xlink:href="#backend-base-state">back-end |
| description</link>) is defined.</para> |
| </listitem> |
| </itemizedlist>For example, a minimum state machine could be defined |
| as:</para> |
| <programlisting>BOOST_MSM_EUML_TRANSITION_TABLE(( |
| ),transition_table) </programlisting> |
| <programlisting>BOOST_MSM_EUML_DECLARE_STATE_MACHINE((transition_table,init_ << Empty ), |
| player_)</programlisting> |
| <para>Please have a look at the player tutorial written using eUML's <link |
| xlink:href="examples/SimpleTutorialEuml2.cpp">first</link> and <link |
| xlink:href="examples/SimpleTutorialEuml.cpp">second</link> syntax. The |
| BOOST_MSM_EUML_DECLARE_ATTRIBUTE macro, to which we will get back shortly, |
| declares attributes given to an eUML type (state or event) using the |
| <command xlink:href="#eUML-attributes">attribute |
| syntax</command>.</para> |
| </sect2> |
| <sect2> |
| <title>Defining a submachine</title> |
| <para>Defining a submachine (see <link |
| xlink:href="examples/CompositeTutorialEuml.cpp">tutorial</link>) 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.</para> |
| <para>Unlike the state or event definition macros, |
| BOOST_MSM_EUML_DECLARE_STATE_MACHINE defines a type, not an instance because |
| a type is what the back-end requires. This means that you will need to |
| declare yourself an instance to reference your submachine into another state |
| machine, for example:</para> |
| <programlisting>BOOST_MSM_EUML_DECLARE_STATE_MACHINE(...,Playing_) |
| typedef msm::back::state_machine<Playing_> Playing_type; |
| Playing_type const Playing;</programlisting> |
| <para>We can now use this instance inside the transition table of the containing |
| state machine:</para> |
| <programlisting>Paused == Playing + pause / pause_playback</programlisting> |
| </sect2> |
| <sect2> |
| <title> |
| <command xml:id="eUML-attributes"/>Attributes / Function call</title> |
| <para>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. It seems like a waste to write a functor for such a simple |
| action. Furthermore, states within MSM are also classes so they can have |
| attributes, and we would also like to provide them with attributes. </para> |
| <para>If you look back at our examples using the <link |
| xlink:href="examples/SimpleTutorialEuml2.cpp">first</link> and <link |
| xlink:href="examples/SimpleTutorialEuml.cpp">second</link> syntaxes, you |
| will find a BOOST_MSM_EUML_DECLARE_ATTRIBUTE and a BOOST_MSM_EUML_ATTRIBUTES |
| macro. The first one declares possible attributes:</para> |
| <programlisting>BOOST_MSM_EUML_DECLARE_ATTRIBUTE(std::string,cd_name) |
| BOOST_MSM_EUML_DECLARE_ATTRIBUTE(DiskTypeEnum,cd_type)</programlisting> |
| <para>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 using the second one:</para> |
| <programlisting>BOOST_MSM_EUML_ATTRIBUTES((attributes_ << cd_name << cd_type ), |
| cd_detected_attributes)</programlisting> |
| <para>This declares an attribute list which is not linked to anything in |
| particular yet. It can be attached to a state or an event. For example, if |
| we want the event cd_detected to have these defined attributes we |
| write:</para> |
| <programlisting>BOOST_MSM_EUML_EVENT_WITH_ATTRIBUTES(cd_detected,cd_detected_attributes)</programlisting> |
| <para>For states, we use the BOOST_MSM_EUML_STATE macro, which has an expression |
| form where one can provide attributes. For example:</para> |
| <programlisting>BOOST_MSM_EUML_STATE((no_action /*entry*/,no_action/*exit*/, |
| attributes_ << cd_detected_attributes), |
| some_state)</programlisting> |
| <para>OK, great, we now have a way 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 |
| reference these attributes directly, at compile-time, in the transition |
| table. For example, in the example, you will find this transition:</para> |
| <programlisting>Stopped==Empty+cd_detected[good_disk_format&&(event_(cd_type)==Int_<DISK_CD>())] </programlisting> |
| <para>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).</para> |
| <para>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.</para> |
| <para>MSM provides more generic objects for state machine types:<itemizedlist> |
| <listitem> |
| <para>event_ : used inside any action, the event triggering the |
| transition</para> |
| </listitem> |
| <listitem> |
| <para>state_: used inside entry and exit actions, the entered / |
| exited state</para> |
| </listitem> |
| <listitem> |
| <para>source_: used inside a transition action, the source |
| state</para> |
| </listitem> |
| <listitem> |
| <para>target_: used inside a transition action, the target |
| state</para> |
| </listitem> |
| <listitem> |
| <para>fsm_: used inside any action, the (lowest-level) state machine |
| processing the transition</para> |
| </listitem> |
| <listitem> |
| <para>Int_<int value>: a functor representing an int</para> |
| </listitem> |
| <listitem> |
| <para>Char_<value>: a functor representing a char</para> |
| </listitem> |
| <listitem> |
| <para>Size_t_<value>: a functor representing a size_t</para> |
| </listitem> |
| <listitem> |
| <para>String_<mpl::string> (boost >= 1.40): a functor |
| representing a string.</para> |
| </listitem> |
| </itemizedlist></para> |
| <para>These helpers can be used in two different ways:<itemizedlist> |
| <listitem> |
| <para>helper(attribute_name) returns the attribute with name |
| attribute_name</para> |
| </listitem> |
| <listitem> |
| <para>helper returns the state / event type itself.</para> |
| </listitem> |
| </itemizedlist></para> |
| <para>The second form is helpful if you want to provide your states with their |
| own methods, which you also want to use inside the transition table. In the |
| <link xlink:href="examples/SimpleTutorialEuml.cpp">above |
| tutorial</link>, 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:</para> |
| <programlisting>MSM_EUML_METHOD(ActivateEmpty_,activate_empty,activate_empty_,void,void)</programlisting> |
| <para>The first parameter is the functor name, for use with the functor |
| front-end. The second is the name of the method to call. The third is the |
| function name for use with eUML, 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 |
| shown generic helpers. We can now use this in a transition, for |
| example:</para> |
| <programlisting>Empty == Open + open_close / (close_drawer,activate_empty_(target_))</programlisting> |
| <para>The action is now defined as a sequence of two actions: close_drawer and |
| activate_empty, which is 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_).</para> |
| <para>More examples can be found in the <link |
| xlink:href="examples/CompilerStressTestEuml.cpp">terrible compiler |
| stress test</link>, the <link xlink:href="examples/SimpleTimer.cpp" |
| >timer example</link> or in the <link |
| xlink:href="examples/iPodSearchEuml.cpp">iPodSearch with eUML</link> |
| (for String_ and more).</para> |
| </sect2> |
| <sect2> |
| <title>Orthogonal regions, flags, event deferring</title> |
| <para>Defining orthogonal regions really means providing more initial states. To |
| add more initial states, “shift left” some, for example, if we had another |
| initial state named AllOk :</para> |
| <programlisting>BOOST_MSM_EUML_DECLARE_STATE_MACHINE((transition_table, |
| init_ << Empty << AllOk ), |
| player_)</programlisting> |
| <para>You remember from the <command xlink:href="#eUML-build-state" |
| >BOOST_MSM_EUML_STATE </command> and <command |
| xlink:href="#eUML-build-sm" |
| >BOOST_MSM_EUML_DECLARE_STATE_MACHINE</command> signatures that just |
| after attributes, we can define flags, like in the basic MSM front-end. To |
| do this, we have another "shift-left" grammar, for example:</para> |
| <programlisting>BOOST_MSM_EUML_STATE((no_action,no_action, attributes_ <<no_attributes_, |
| /* flags */ configure_<< PlayingPaused << CDLoaded), |
| Paused)</programlisting> |
| <para>We now defined that Paused will get two flags, PlayingPaused and CDLoaded, |
| defined, with another macro:</para> |
| <programlisting>BOOST_MSM_EUML_FLAG(CDLoaded)</programlisting> |
| <para>This corresponds to the following basic front-end definition of |
| Paused:</para> |
| <programlisting>struct Paused : public msm::front::state<> |
| { |
| typedef mpl::vector2<PlayingPaused,CDLoaded> flag_list; |
| };</programlisting> |
| <para>Under the hood, what you get really is a mpl::vector2.</para> |
| <para><emphasis role="underline">Note</emphasis>: As we use the version of |
| BOOST_MSM_EUML_STATE's expression with 4 arguments, we need to tell eUML |
| that we need no attributes. Similarly to a <code>cout << endl</code>, |
| we need a <code>attributes_ << no_attributes_</code> syntax.</para> |
| <para>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 behaviors. For example, in the <link |
| xlink:href="examples/iPodEuml.cpp">iPod implementation with eUML</link>, |
| you find the following transition:</para> |
| <programlisting>ForwardPressed == NoForward + EastPressed[!is_flag_(NoFastFwd)]</programlisting> |
| <para>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.</para> |
| <para>eUML also supports defining deferred events in the state (state machine) |
| definition. To this aim, we can reuse the flag grammar. For example:</para> |
| <programlisting>BOOST_MSM_EUML_STATE((Empty_Entry,Empty_Exit, attributes_ << no_attributes_, |
| /* deferred */ configure_<< play ),Empty) </programlisting> |
| <para>The configure_ left shift is also responsible for deferring events. Shift |
| inside configure_ a flag and the state will get a flag, shift an event and |
| it will get a deferred event. This replaces the basic front-end |
| definition:</para> |
| <programlisting>typedef mpl::vector<play> deferred_events;</programlisting> |
| <para>In <link xlink:href="examples/OrthogonalDeferredEuml.cpp">this |
| tutorial</link>, player is defining a second orthogonal region with |
| AllOk as initial state. The <code>Empty</code> and <code>Open</code> states |
| also defer the event <code>play</code>. <code>Open</code>, |
| <code>Stopped</code> and <code>Pause</code> also support the flag |
| <code>CDLoaded</code> using the same left shift into |
| <code>configure_</code>.</para> |
| <para>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 |
| <link xlink:href="examples/OrthogonalDeferredEuml.cpp">this |
| tutorial</link>. You will find the following transition:</para> |
| <programlisting>Open + play / defer_</programlisting> |
| <para>This is an <command xlink:href="#eUML-internal">internal |
| transition</command>. Ignore it for the moment. Interesting is, that |
| when the event <code>play</code> is fired and <code>Open</code> is active, |
| the event will be deferred. Now add a guard and you can conditionally defer |
| the event, for example:</para> |
| <programlisting>Open + play [ some_condition ] / defer_</programlisting> |
| <para>This is similar to what we did with the functor front-end. This means that |
| we have the same constraints. 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:</para> |
| <programlisting>BOOST_MSM_EUML_DECLARE_STATE_MACHINE((transition_table, |
| init_ << Empty << AllOk, |
| Entry_Action, |
| Exit_Action, |
| attributes_ << no_attributes_, |
| configure_<< deferred_events ), |
| player_)</programlisting> |
| <para>A <link xlink:href="examples/OrthogonalDeferredEuml2.cpp">tutorial</link> |
| illustrates this possibility.</para> |
| </sect2> |
| <sect2> |
| <title> |
| <command xml:id="eUML-Configuration"/>Customizing a state machine / Getting |
| more speed</title> |
| <para>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 the other front-ends:<itemizedlist> |
| <listitem> |
| <para><code>configure_ << no_exception</code>: disables |
| exception handling</para> |
| </listitem> |
| <listitem> |
| <para><code>configure_ << no_msg_queue</code> deactivates the |
| message queue</para> |
| </listitem> |
| <listitem> |
| <para><code>configure_ << deferred_events</code> manually |
| enables event deferring</para> |
| </listitem> |
| </itemizedlist></para> |
| <para>Deactivating the first two features and not activating the third if not |
| needed greatly improves the event dispatching speed of your state machine. |
| Our <link xlink:href="examples/EumlSimple.cpp">speed testing</link> example |
| with eUML does this for the best performance.</para> |
| <para><emphasis role="underline">Important note</emphasis>: As exit pseudo |
| states are using the message queue to forward events out of a submachine, |
| the <code>no_message_queue</code> option cannot be used with state machines |
| containing an exit pseudo state.</para> |
| </sect2> |
| <sect2> |
| <title>Completion / Anonymous transitions</title> |
| <para>Anonymous transitions (See <command xlink:href="#uml-anonymous">UML |
| tutorial</command>) are transitions without a named event, which are |
| therefore triggered immediately when the source state becomes 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: </para> |
| <programlisting>State3 == State4 [always_true] / State3ToState4 |
| State4 [always_true] / State3ToState4 == State3</programlisting> |
| <para>Please have a look at <link |
| xlink:href="examples/AnonymousTutorialEuml.cpp">this example</link>, |
| which implements the <command xlink:href="#anonymous-transitions">previously |
| defined</command> state machine with eUML.</para> |
| </sect2> |
| <sect2> |
| <title><command xml:id="eUML-internal"/>Internal transitions</title> |
| <para>Like both other front-ends, eUML supports two ways of defining internal transitions:<itemizedlist> |
| <listitem> |
| <para>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:</para> |
| <programlisting>Open + open_close [internal_guard1] / internal_action1</programlisting> |
| <para><link xlink:href="examples/EumlInternal.cpp">A full |
| example</link> is also provided.</para> |
| </listitem> |
| <listitem> |
| <para>in a state's <code>internal_transition_table</code>. For |
| example:</para> |
| <programlisting>BOOST_MSM_EUML_DECLARE_STATE((Open_Entry,Open_Exit),Open_def) |
| struct Open_impl : public Open_def |
| { |
| BOOST_MSM_EUML_DECLARE_INTERNAL_TRANSITION_TABLE(( |
| open_close [internal_guard1] / internal_action1 |
| )) |
| };</programlisting> |
| <para>Notice how we do not need to repeat that the transition |
| originates from Open as we already are in Open's context. </para> |
| <para>The <link xlink:href="examples/EumlInternalDistributed.cpp" |
| >implementation</link> 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).</para> |
| </listitem> |
| </itemizedlist></para> |
| </sect2> |
| <sect2> |
| <title>Other state types</title> |
| <para>We saw the <command xlink:href="#eUML-build-state">build_state</command> |
| function, which creates a simple state. Likewise, eUML provides other |
| state-building macros for other types of states:<itemizedlist> |
| <listitem> |
| <para>BOOST_MSM_EUML_TERMINATE_STATE takes the same arguments as |
| BOOST_MSM_EUML_STATE and defines, well, a terminate |
| state.</para> |
| </listitem> |
| <listitem> |
| <para>BOOST_MSM_EUML_INTERRUPT_STATE takes the same arguments as |
| BOOST_MSM_EUML_STATE and defines an interrupt state. However, |
| the expression argument must contain as first element the event |
| ending the interruption, for example: |
| <code>BOOST_MSM_EUML_INTERRUPT_STATE(( end_error /*end |
| interrupt event*/,ErrorMode_Entry,ErrorMode_Exit |
| ),ErrorMode)</code></para> |
| </listitem> |
| <listitem> |
| <para>BOOST_MSM_EUML_EXIT_STATE takes the same arguments as |
| BOOST_MSM_EUML_STATE and defines an exit pseudo state. However, |
| the expression argument must contain as first element the event |
| propagated from the exit point: |
| <code>BOOST_MSM_EUML_EXIT_STATE(( event6 /*propagated |
| event*/,PseudoExit1_Entry,PseudoExit1_Exit |
| ),PseudoExit1)</code></para> |
| </listitem> |
| <listitem> |
| <para>BOOST_MSM_EUML_EXPLICIT_ENTRY_STATE defines an entry pseudo |
| state. It takes 3 parameters: the region index to be entered is |
| defined as an int argument, followed by the configuration |
| expression like BOOST_MSM_EUML_STATE and the state name, so that |
| <code>BOOST_MSM_EUML_EXPLICIT_ENTRY_STATE(0 /*region |
| index*/,( SubState2_Entry,SubState2_Exit ),SubState2)</code> |
| defines an entry state into the first region of a |
| submachine.</para> |
| </listitem> |
| <listitem> |
| <para>BOOST_MSM_EUML_ENTRY_STATE defines an entry pseudo state. It |
| takes 3 parameters: the region index to be entered is defined as |
| an int argument, followed by the configuration expression like |
| BOOST_MSM_EUML_STATE and the state name, so that |
| <code>BOOST_MSM_EUML_ENTRY_STATE(0,( |
| PseudoEntry1_Entry,PseudoEntry1_Exit ),PseudoEntry1)</code> |
| defines a pseudo entry state into the first region of a |
| submachine.</para> |
| </listitem> |
| </itemizedlist></para> |
| <para>To use these states in the transition table, eUML offers the functions |
| <code>explicit_</code>, <code>exit_pt_</code> and |
| <code>entry_pt_</code>. For example, a direct entry into the substate |
| SubState2 from SubFsm2 could be:</para> |
| <programlisting>explicit_(SubFsm2,SubState2) == State1 + event2</programlisting> |
| <para>Forks being a list on direct entries, eUML supports a logical syntax |
| (state1, state2, ...), for example:</para> |
| <programlisting>(explicit_(SubFsm2,SubState2), |
| explicit_(SubFsm2,SubState2b), |
| explicit_(SubFsm2,SubState2c)) == State1 + event3 </programlisting> |
| <para>An entry point is entered using the same syntax as explicit entries: |
| <programlisting>entry_pt_(SubFsm2,PseudoEntry1) == State1 + event4</programlisting></para> |
| <para>For exit points, it is again the same syntax except that exit points are |
| used as source of the transition: |
| <programlisting>State2 == exit_pt_(SubFsm2,PseudoExit1) + event6 </programlisting></para> |
| <para>The <link xlink:href="examples/DirectEntryEuml.cpp">entry tutorial</link> |
| is also available with eUML.</para> |
| </sect2> |
| <sect2> |
| <title>Helper functions</title> |
| <para>We saw a few helpers but there are more, so let us have a more complete description:<itemizedlist> |
| <listitem> |
| <para>event_ : used inside any action, the event triggering the |
| transition</para> |
| </listitem> |
| <listitem> |
| <para>state_: used inside entry and exit actions, the entered / |
| exited state</para> |
| </listitem> |
| <listitem> |
| <para>source_: used inside a transition action, the source |
| state</para> |
| </listitem> |
| <listitem> |
| <para>target_: used inside a transition action, the target |
| state</para> |
| </listitem> |
| <listitem> |
| <para>fsm_: used inside any action, the (deepest-level) state |
| machine processing the transition</para> |
| </listitem> |
| <listitem> |
| <para>These objects can also be used as a function and return an |
| attribute, for example event_(cd_name)</para> |
| </listitem> |
| <listitem> |
| <para>Int_<int value>: a functor representing an int</para> |
| </listitem> |
| <listitem> |
| <para>Char_<value>: a functor representing a char</para> |
| </listitem> |
| <listitem> |
| <para>Size_t_<value>: a functor representing a size_t</para> |
| </listitem> |
| <listitem> |
| <para>True_ and False_ functors returning true and false |
| respectively</para> |
| </listitem> |
| <listitem> |
| <para>String_<mpl::string> (boost >= 1.40): a functor |
| representing a string.</para> |
| </listitem> |
| <listitem> |
| <para>if_then_else_(guard, action, action) where action can be an |
| action sequence</para> |
| </listitem> |
| <listitem> |
| <para>if_then_(guard, action) where action can be an action |
| sequence</para> |
| </listitem> |
| <listitem> |
| <para>while_(guard, action) where action can be an action |
| sequence</para> |
| </listitem> |
| <listitem> |
| <para>do_while_(guard, action) where action can be an action |
| sequence</para> |
| </listitem> |
| <listitem> |
| <para>for_(action, guard, action, action) where action can be an |
| action sequence</para> |
| </listitem> |
| <listitem> |
| <para>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</para> |
| </listitem> |
| <listitem> |
| <para>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</para> |
| </listitem> |
| <listitem> |
| <para>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</para> |
| </listitem> |
| <listitem> |
| <para>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</para> |
| </listitem> |
| </itemizedlist></para> |
| <para>This can be quite fun. For example, </para> |
| <programlisting>/( if_then_else_(--fsm_(m_SongIndex) > Int_<0>(),/*if clause*/ |
| show_playing_song, /*then clause*/ |
| (fsm_(m_SongIndex)=Int_<1>(),process_(EndPlay))/*else clause*/ |
| ) |
| )</programlisting> |
| <para>means: if (fsm.SongIndex > 0, call show_playing_song else |
| {fsm.SongIndex=1; process EndPlay on fsm;}</para> |
| <para>A few examples are using these features:<itemizedlist> |
| <listitem> |
| <para>the iPod example introduced at the BoostCon09 <link |
| xlink:href="examples/iPodEuml.cpp">has been rewritten</link> |
| with eUML (weak compilers please move on...)</para> |
| </listitem> |
| <listitem> |
| <para>the iPodSearch example also introduced at the BoostCon09 <link |
| xlink:href="examples/iPodSearchEuml.cpp">has been |
| rewritten</link> with eUML. In this example, you will also |
| find some examples of STL functor usage.</para> |
| </listitem> |
| <listitem> |
| <para><link xlink:href="examples/SimpleTimer.cpp">A simpler |
| timer</link> example is a good starting point. </para> |
| </listitem> |
| </itemizedlist></para> |
| <para>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, <emphasis role="underline">except</emphasis>, for the |
| moment, with the while_, if_then_, if_then_else_ functions.</para> |
| </sect2> |
| <sect2> |
| <title>Phoenix-like STL support</title> |
| <para>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 further reduce the need for your own functors for |
| the transition table. 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:<itemizedlist> |
| <listitem> |
| <para>begin_(container), end_(container): return iterators of a |
| container.</para> |
| </listitem> |
| <listitem> |
| <para>empty_(container): returns container.empty()</para> |
| </listitem> |
| <listitem> |
| <para>clear_(container): container.clear()</para> |
| </listitem> |
| <listitem> |
| <para>transform_ : std::transform</para> |
| </listitem> |
| </itemizedlist></para> |
| <para>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 <link xlink:href="#Reference-begin">reference</link> |
| lists all eUML functions 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 functors for STL algorithms are to be found in:</para> |
| <programlisting>#include <msm/front/euml/algorithm.hpp></programlisting> |
| <para>The algorithms are also divided into sub-headers, matching the phoenix |
| structure for simplicity:</para> |
| <programlisting>#include < msm/front/euml/iteration.hpp> |
| #include < msm/front/euml/transformation.hpp> |
| #include < msm/front/euml/querying.hpp> </programlisting> |
| <para>Container methods can be found in:</para> |
| <programlisting>#include < msm/front/euml/container.hpp></programlisting> |
| <para>Or one can simply include the whole STL support (you will also need to |
| include euml.hpp):</para> |
| <programlisting>#include < msm/front/euml/stl.hpp></programlisting> |
| <para>A few examples (to be found in <link |
| xlink:href="examples/iPodSearchEuml.cpp">this tutorial</link>):<itemizedlist> |
| <listitem> |
| <para><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</para> |
| </listitem> |
| <listitem> |
| <para><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</para> |
| </listitem> |
| </itemizedlist></para> |
| </sect2> |
| </sect1> |
| <sect1> |
| <title>Back-end</title> |
| <para>There is, at the moment, one back-end. This back-end contains the library |
| engine and defines the performance and functionality trade-offs. 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.</para> |
| <sect2> |
| <title>Creation </title> |
| <para>MSM being divided between front and back-end, one needs to first define a |
| front-end. Then, to create a real state machine, the back-end must be |
| declared: |
| <programlisting>typedef msm::back::state_machine<my_front_end> my_fsm;</programlisting></para> |
| <para>We now have a fully functional state machine type. The next sections will |
| describe what can be done with it.</para> |
| </sect2> |
| <sect2> |
| <title><command xml:id="backend-start"/>Starting a state machine</title> |
| <para>The <code>start</code> method starts the state machine, meaning it will |
| activate the initial state, which means in turn that the initial state's |
| entry behavior will be called. We need the start method because you do not |
| always want the entry behavior of the initial state to be called immediately |
| but only when your state machine is ready to process events. A good example |
| of this is when you use a state machine to write an algorithm and each loop |
| back to the initial state is an algorithm call. Each call to start will make |
| the algorithm run once. The <link xlink:href="examples/iPodSearch.cpp" |
| >iPodSearch</link> example uses this possibility.</para> |
| </sect2> |
| <sect2> |
| <title>Event dispatching</title> |
| <para>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 instances of some_event, 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 create one on the fly or |
| instantiate if before processing: </para> |
| <programlisting>my_fsm fsm; fsm.process_event(some_event()); |
| some_event e1; fsm.process_event(e1)</programlisting> |
| <para>Creating an event on the fly will be optimized by the compiler so the |
| performance will not degrade.</para> |
| </sect2> |
| <sect2> |
| <title>Active state(s)</title> |
| <para>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, <command |
| xlink:href="#UML-internal-transition">internal transitions</command> or |
| <command xlink:href="#backend-visitor">visitors</command> 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 |
| <command xlink:href="#internals-state-id">internals section</command> to |
| know how state ids are generated.</para> |
| </sect2> |
| <sect2> |
| <title><command xml:id="back-end-serialization"/>Serialization</title> |
| <para>A common need is the ability to save a state machine and restore it at a |
| different time. MSM supports this feature for the basic and functor |
| front-ends, and in a more limited manner for eUML. MSM supports |
| boost::serialization out of the box (by offering a <code>serialize</code> |
| function). Actually, for basic serialization, you need not do much, a MSM |
| state machine is serializable almost like any other type. Without any |
| special work, you can make a state machine remember its state, for |
| example:</para> |
| <para> |
| <programlisting>MyFsm fsm; |
| // write to archive |
| std::ofstream ofs("fsm.txt"); |
| // save fsm to archive |
| { |
| boost::archive::text_oarchive oa(ofs); |
| // write class instance to archive |
| oa << fsm; |
| } </programlisting> |
| </para> |
| <para>Loading back is very similar:</para> |
| <para> |
| <programlisting>MyFsm fsm; |
| { |
| // create and open an archive for input |
| std::ifstream ifs("fsm.txt"); |
| boost::archive::text_iarchive ia(ifs); |
| // read class state from archive |
| ia >> fsm; |
| } </programlisting> |
| </para> |
| <para>This will (de)serialize the state machine itself but not the concrete |
| states' data. This can be done on a per-state basis to reduce the amount of |
| typing necessary. To allow serialization of a concrete state, provide a |
| do_serialize typedef and implement the serialize function:</para> |
| <para> |
| <programlisting>struct Empty : public msm::front::state<> |
| { |
| // we want Empty to be serialized. First provide the typedef |
| typedef int do_serialize; |
| // then implement serialize |
| template<class Archive> |
| void serialize(Archive & ar, const unsigned int /* version */) |
| { |
| ar & some_dummy_data; |
| } |
| Empty():some_dummy_data(0){} |
| int some_dummy_data; |
| }; </programlisting> |
| </para> |
| <para>You can also serialize data contained in the front-end class. Again, you |
| need to provide the typedef and implement serialize:</para> |
| <para> |
| <programlisting>struct player_ : public msm::front::state_machine_def<player_> |
| { |
| //we might want to serialize some data contained by the front-end |
| int front_end_data; |
| player_():front_end_data(0){} |
| // to achieve this, provide the typedef |
| typedef int do_serialize; |
| // and implement serialize |
| template<class Archive> |
| void serialize(Archive & ar, const unsigned int ) |
| { |
| ar & front_end_data; |
| } |
| ... |
| }; </programlisting> |
| </para> |
| <para>The saving of the back-end data (the current state(s)) is valid for all |
| front-ends, so a front-end written using eUML can be serialized. However, to |
| serialize a concrete state, the macros like |
| <code>BOOST_MSM_EUML_STATE</code> cannot be used, so the state will have |
| to be implemented by directly inheriting from |
| <code>front::euml::euml_state</code>.</para> |
| <para>The only limitiation is that the event queues cannot be serialized so |
| serializing must be done in a stable state, when no event is being |
| processed. You can serialize during event processing only if using no queue |
| (deferred or event queue).</para> |
| <para>This <link |
| xlink:href="examples/Serialize.cpp">example</link> shows a state machine which we serialize after processing an |
| event. The <code>Empty</code> state also has some data to serialize.</para> |
| </sect2> |
| <sect2> |
| <title><command xml:id="backend-base-state"/>Base state type </title> |
| <para>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. Note 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:<itemizedlist> |
| <listitem> |
| <para>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: |
| <programlisting>struct Empty : public msm::front::state<my_base_state></programlisting> |
| 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, |
| <code>msm::front::polymorphic_state</code> |
| </para> |
| </listitem> |
| <listitem> |
| <para>Add the user-defined base state in the state machine frontend |
| definition, as a second template argument, for example: |
| <programlisting>struct player_ : public msm::front::state_machine<player_,my_base_state> </programlisting></para> |
| </listitem> |
| </itemizedlist></para> |
| <para>You can also ask for a state with a given id (which you might have gotten |
| from current_state()) using <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 polymorphically.</para> |
| </sect2> |
| <sect2> |
| <title><command xml:id="backend-visitor"/>Visitor</title> |
| <para>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!</para> |
| <para>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>accept_sig</code> typedef giving the |
| return value (unused for the moment) and parameters 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:</para> |
| <programlisting>struct my_visitable_state |
| { |
| // signature of the accept function |
| typedef args<void> accept_sig; |
| // we also want polymorphic states |
| virtual ~my_visitable_state() {} |
| // default implementation for states who do not need to be visited |
| void accept() const {} |
| };</programlisting> |
| <para>This makes your states polymorphic and visitable. In this case, accept is |
| made const and takes no argument. It could also be:</para> |
| <programlisting>struct SomeVisitor {…}; |
| struct my_visitable_state |
| { |
| // signature of the accept function |
| typedef args<void,SomeVisitor&> accept_sig; |
| // we also want polymorphic states |
| virtual ~my_visitable_state() {} |
| // default implementation for states who do not need to be visited |
| void accept(SomeVisitor&) const {} |
| };</programlisting> |
| <para>And now, <code>accept</code> will take one argument (it could also be |
| non-const). By default, <code>accept</code> takes up to 2 arguments. To get |
| more, set #define BOOST_MSM_VISITOR_ARG_SIZE to another value before |
| including state_machine.hpp. For example:</para> |
| <programlisting>#define BOOST_MSM_VISITOR_ARG_SIZE 3 |
| #include <boost/msm/back/state_machine.hpp></programlisting> |
| <para>Note that accept will be called on ALL active states <emphasis |
| role="underline">and also automatically on sub-states of a |
| submachine</emphasis>.</para> |
| <para><emphasis role="underline">Important warning</emphasis>: 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:</para> |
| <programlisting>SomeVisitor vis; sm.visit_current_states(boost::ref(vis));</programlisting> |
| <para>This <link xlink:href="examples/SM-2Arg.cpp">example</link> uses a |
| visiting function with 2 arguments.</para> |
| </sect2> |
| <sect2> |
| <title>Flags</title> |
| <para>Flags is a MSM-only concept, supported by all front-ends, which base |
| themselves on the functions: </para> |
| <programlisting>template <class Flag> bool is_flag_active() |
| template <class Flag,class BinaryOp> bool is_flag_active()</programlisting> |
| <para>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:</para> |
| <programlisting>my_fsm.is_flag_active<MyFlag>() |
| my_fsm.is_flag_active<MyFlag,my_fsm_type::Flag_OR>()</programlisting> |
| <para>Please refer to the front-ends sections for usage examples.</para> |
| </sect2> |
| <sect2> |
| <title>Getting a state</title> |
| <para>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: </para> |
| <programlisting>player::Stopped* tempstate = p.get_state<player::Stopped*>();</programlisting> |
| <para> or </para> |
| <programlisting>player::Stopped& tempstate2 = p.get_state<player::Stopped&>();</programlisting> |
| <para>depending on your personal taste. </para> |
| </sect2> |
| <sect2> |
| <title><command xml:id="backend-fsm-constructor-args"/> State machine constructor with arguments </title> |
| <para>You might want to define a state machine with a non-default constructor. |
| For example, you might want to write: </para> |
| <programlisting>struct player_ : public msm::front::state_machine_def<player_> |
| { |
| player_(int some_value){…} |
| }; </programlisting> |
| <para>This is possible, using the back-end as forwarding object: </para> |
| <programlisting>typedef msm::back::state_machine<player_ > player; player p(3);</programlisting> |
| <para>The back-end will call the corresponding front-end constructor upon |
| creation.</para> |
| <para>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 overwrite the default. </para> |
| <para>You can also pass arguments by reference (or const-reference) using |
| boost::ref (or boost::cref):</para> |
| <programlisting>struct player_ : public msm::front::state_machine_def<player_> |
| { |
| player_(SomeType& t, int some_value){…} |
| }; |
| |
| typedef msm::back::state_machine<player_ > player; |
| SomeType data; |
| player p(boost::ref(data),3); |
| </programlisting> |
| <para>Normally, MSM default-constructs all its states or submachines. There are |
| however cases where you might not want this. An example is when you use a |
| state machine as submachine, and this submachine used the above defined |
| constructors. You can add as first argument of the state machine constructor |
| an expression where existing states are passed and copied:</para> |
| <programlisting>player p( back::states_ << state_1 << ... << state_n , boost::ref(data),3);</programlisting> |
| <para>Where state_1..n are instances of some or all of the states of the state |
| machine. Submachines being state machines, this can recurse, for example, if |
| Playing is a submachine containing a state Song1 having itself a constructor |
| where some data is passed:</para> |
| <programlisting>player p( back::states_ << Playing(back::states_ << Song1(some_Song1_data)) , |
| boost::ref(data),3);</programlisting> |
| <para>It is also possible to replace a given state by a new instance at any time |
| using <code>set_states()</code> and the same syntax, for example: |
| <programlisting>p.set_states( back::states_ << state_1 << ... << state_n );</programlisting></para> |
| <para>An <link xlink:href="examples/Constructor.cpp" |
| >example</link> making intensive use of this capability is provided.</para> |
| </sect2> |
| <sect2> |
| <title><command xml:id="backend-tradeof-rt-ct"/>Trading run-time speed for |
| better compile-time / multi-TU compilation</title> |
| <para>MSM is optimized for run-time speed at the cost of longer compile-time. |
| This can become a problem with older compilers and big state machines, |
| especially if you don't really care about run-time speed that much and would |
| be satisfied by a performance roughly the same as most state machine |
| libraries. MSM offers a back-end policy to help there. But before you try |
| it, if you are using a VC compiler, deactivate the /Gm compiler option |
| (default for debug builds). This option can cause builds to be 3 times |
| longer... If the compile-time still is a problem, read further. MSM offers a |
| policy which will speed up compiling in two main cases:<itemizedlist> |
| <listitem> |
| <para>many transition conflicts</para> |
| </listitem> |
| <listitem> |
| <para>submachines</para> |
| </listitem> |
| </itemizedlist></para> |
| <para>The back-end <code>msm::back::state_machine</code> has a third template |
| argument (first is the front-end, second is the history policy) defaulting |
| to <code>favor_runtime_speed</code>. To switch to |
| <code>favor_compile_time</code>, which is declared in |
| <code><msm/back/favor_compile_time.hpp></code>, you need to:<itemizedlist> |
| <listitem> |
| <para>switch the policy to <code>favor_compile_time</code> for the |
| main state machine (and possibly submachines)</para> |
| </listitem> |
| <listitem> |
| <para>move the submachine declarations into their own header which |
| includes |
| <code><msm/back/favor_compile_time.hpp></code></para> |
| </listitem> |
| <listitem> |
| <para>add for each submachine a cpp file including your header and |
| calling a macro, which generates helper code, for |
| example:</para> |
| <programlisting>#include "mysubmachine.hpp" |
| BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(mysubmachine)</programlisting> |
| </listitem> |
| <listitem> |
| <para>configure your compiler for multi-core compilation</para> |
| </listitem> |
| </itemizedlist></para> |
| <para>You will now compile your state machine on as many cores as you have |
| submachines, which will greatly speed up the compilation if you factor your |
| state machine into smaller submachines.</para> |
| <para>Independently, transition conflicts resolution will also be much |
| faster.</para> |
| <para>This policy uses boost.any behind the hood, which means that we will lose |
| one feature which MSM offers with the default policy, <link |
| xlink:href="#event-hierarchy">event hierarchy</link>. The following |
| example takes our iPod example and speeds up compile-time by using this |
| technique. We have:<itemizedlist> |
| <listitem> |
| <para><link xlink:href="examples/iPod_distributed/iPod.cpp">our main |
| state machine and main function</link></para> |
| </listitem> |
| <listitem> |
| <para><link xlink:href="examples/iPod_distributed/PlayingMode.hpp" |
| >PlayingMode moved to a separate header</link></para> |
| </listitem> |
| <listitem> |
| <para><link xlink:href="examples/iPod_distributed/PlayingMode.cpp">a |
| cpp for PlayingMode</link></para> |
| </listitem> |
| <listitem> |
| <para><link xlink:href="examples/iPod_distributed/MenuMode.hpp" |
| >MenuMode moved to a separate header</link></para> |
| </listitem> |
| <listitem> |
| <para><link xlink:href="examples/iPod_distributed/MenuMode.cpp">a |
| cpp for MenuMode</link></para> |
| </listitem> |
| <listitem> |
| <para><link xlink:href="examples/iPod_distributed/Events.hpp">events |
| move to a separate header as all machines use |
| it</link></para> |
| </listitem> |
| </itemizedlist> |
| </para> |
| </sect2> |
| </sect1> |
| </chapter> |
| <chapter> |
| <title> Performance / Compilers</title> |
| <para>Tests were made on different PCs running Windows XP and Vista and compiled with |
| VC9 SP1 or Ubuntu and compiled with g++ 4.2 and 4.3. For these tests, the same |
| player state machine was written using Boost.Statechart, as a <link |
| xlink:href="examples/SCSimple.cpp">state machine with only simple states</link> |
| and as a <link xlink:href="examples/SCComposite.cpp">state machine with a composite |
| state</link>. The same simple and composite state machines are implemented with |
| MSM with a standard frontend <link xlink:href="examples/MsmSimple.cpp" |
| >(simple)</link><link xlink:href="examples/MsmComposite.cpp">(composite)</link>, |
| the simple one also with <link xlink:href="examples/MsmSimpleFunctors.cpp" |
| >functors</link> and with <link xlink:href="examples/EumlSimple.cpp" |
| >eUML</link>. As these simple machines need no terminate/interrupt states, no |
| message queue and have no-throw guarantee on their actions, the MSM state machines |
| are defined with minimum functionality. Test machine is a Q6600 2.4GHz, Vista |
| 64.</para> |
| <sect1> |
| <title>Speed</title> |
| <para>VC9:<itemizedlist> |
| <listitem> |
| <para>The simple test completes 90 times faster with MSM than with |
| Boost.Statechart</para> |
| </listitem> |
| <listitem> |
| <para>The composite test completes 25 times faster with MSM</para> |
| </listitem> |
| </itemizedlist></para> |
| <para>gcc 4.2.3 (Ubuntu 8.04 in VMWare, same PC):<itemizedlist> |
| <listitem> |
| <para>The simple test completes 46 times faster with MSM</para> |
| </listitem> |
| <listitem> |
| <para>The composite test completes 19 times faster with Msm</para> |
| </listitem> |
| </itemizedlist></para> |
| </sect1> |
| <sect1> |
| <title>Executable size</title> |
| <para>There are some worries that MSM generates huge code. Is it true? The 2 |
| compilers I tested disagree with this claim. On VC9, the test state machines |
| used in the performance section produce executables of 14kB (for simple and |
| eUML) and 21kB (for the composite). This includes the test code and iostreams. |
| By comparison, an empty executable with iostreams generated by VC9 has a size of |
| 7kB. Boost.Statechart generates executables of 43kB and 54kB. As a bonus, eUML |
| comes for “free” in terms of executable size. You even get a speed gain. With |
| g++ 4.3, it strongly depends on the compiler options (much more than VC). A good |
| size state machine with –O3 can generate an executable of 600kB, and with eUML |
| you can get to 1.5MB. Trying with –Os –s I come down to 18kB and 30kB for the |
| test state machines, while eUML will go down to 1MB (which is still big), so in |
| this case eUML does not come for free.</para> |
| </sect1> |
| <sect1> |
| <title>Supported compilers</title> |
| <para>For a current status, have a look at the <link |
| xlink:href="http://www.boost.org/development/tests/trunk/developer/msm.html" |
| >regression tests</link>.</para> |
| <para>MSM was successfully tested with: <itemizedlist> |
| <listitem> |
| <para>VC8 (partly), VC9, VC10</para> |
| </listitem> |
| <listitem> |
| <para>g++ 4.0.1 and higher</para> |
| </listitem> |
| <listitem> |
| <para>Intel 10.1 and higher</para> |
| </listitem> |
| <listitem> |
| <para>Clang 2.9</para> |
| </listitem> |
| <listitem> |
| <para>Green Hills Software MULTI for ARM v5.0.5 patch 4416 (Simple and |
| Composite tutorials)</para> |
| </listitem> |
| <listitem> |
| <para>Partial support for IBM compiler</para> |
| </listitem> |
| </itemizedlist></para> |
| <para>VC8 and to some lesser extent VC9 suffer from a bug. Enabling the option |
| "Enable Minimal Rebuild" (/Gm) will cause much higher compile-time (up to three |
| times with VC8!). This option being activated per default in Debug mode, this |
| can be a big problem.</para> |
| </sect1> |
| <sect1> |
| <title> Limitations </title> |
| <para> |
| <itemizedlist> |
| <listitem> |
| <para>Compilation times of state machines with > 80 transitions that are |
| going to make you storm the CFO's office and make sure you get a |
| shiny octocore with 12GB RAM by next week, unless he's interested in |
| paying you watch the compiler agonize for hours... (Make sure you |
| ask for dual 24" as well, it doesn't hurt).</para> |
| </listitem> |
| <listitem> |
| <para>eUML allows very long constructs but will also quickly increase |
| your compile time on some compilers (VC9, VC10) with buggy decltype |
| support (I suspect some at least quadratic algorithms there). Even |
| g++ 4.4 shows some regression compared to 4.3 and will crash if the |
| constructs become too big.</para> |
| </listitem> |
| <listitem> |
| <para>Need to overwrite the mpl::vector/list default-size-limit of 20 |
| and fusion default vector size of 10 if more than 10 states found in |
| a state machine</para> |
| </listitem> |
| </itemizedlist> |
| </para> |
| </sect1> |
| <sect1> |
| <title> Compilers corner </title> |
| <para>Compilers are sometimes full of surprises and such strange errors happened in |
| the course of the development that I wanted to list the most fun for readers’ |
| entertainment.</para> |
| <para><emphasis role="underline">VC8</emphasis>: </para> |
| <programlisting>template <class StateType> |
| typename ::boost::enable_if< |
| typename ::boost::mpl::and_< |
| typename ::boost::mpl::not_< |
| typename has_exit_pseudo_states<StateType>::type |
| >::type, |
| typename ::boost::mpl::not_< |
| typename is_pseudo_exit<StateType>::type |
| >::type |
| >::type, |
| BaseState*>::type </programlisting> |
| <para>I get the following error:</para> |
| <para>error C2770: invalid explicit template argument(s) for '`global |
| namespace'::boost::enable_if<...>::...' </para> |
| <para>If I now remove the first “::” in ::boost::mpl , the compiler shuts up. So in |
| this case, it is not possible to follow Boost’s guidelines.</para> |
| <para><emphasis role="underline">VC9</emphasis>:<itemizedlist> |
| <listitem> |
| <para>This one is my all times’ favorite. Do you know why the exit |
| pseudo states are referenced in the transition table with a |
| “submachine::exit_pt” ? Because “exit” will crash the compiler. |
| “Exit” is not possible either because it will crash the compiler on |
| one machine, but not on another (the compiler was installed from the |
| same disk).</para> |
| </listitem> |
| <listitem> |
| <para>Sometimes, removing a policy crashes the compiler, so some |
| versions are defining a dummy policy called WorkaroundVC9.</para> |
| </listitem> |
| <listitem> |
| <para>Typeof: While g++ and VC9 compile “standard” state machines in |
| comparable times, Typeof (while in both ways natively supported) |
| seems to behave in a quadratic complexity with VC9 and VC10.</para> |
| </listitem> |
| <listitem> |
| <para>eUML: in case of a compiler crash, changing the order of state |
| definitions (first states without entry or exit) sometimes solves |
| the problem.</para> |
| </listitem> |
| </itemizedlist></para> |
| <para><emphasis role="underline">g++ 4.x</emphasis>: Boring compiler, almost all is |
| working almost as expected. Being not a language lawyer I am unsure about the |
| following “Typeof problem”. VC9 and g++ disagree on the question if you can |
| derive from the BOOST_TYPEOF generated type without first defining a typedef. I |
| will be thankful for an answer on this. I only found two ways to break the compiler:<itemizedlist> |
| <listitem> |
| <para>Add more eUML constructs until something explodes (especially with |
| g++-4.4) </para> |
| </listitem> |
| <listitem> |
| <para>The build_terminate function uses 2 mpl::push_back instead of |
| mpl::insert_range because g++ would not accept insert_range.</para> |
| </listitem> |
| </itemizedlist></para> |
| <para>You can test your compiler’s decltype implementation with the <link |
| xlink:href="examples/CompilerStressTestEuml.cpp">following stress |
| test</link> and reactivate the commented-out code until the compiler |
| crashes.</para> |
| </sect1> |
| </chapter> |
| <chapter> |
| <title>Questions & Answers</title> |
| <para><emphasis role="underline">Question</emphasis>: on_entry gets as argument, the |
| sent event. What event do I get when the state becomes default-activated (because it |
| is an initial state)?</para> |
| <para> |
| <emphasis role="underline">Answer</emphasis>: To allow you to know that the state |
| was default-activated, MSM generates a boost::msm::InitEvent default event. </para> |
| <para><emphasis role="underline">Question</emphasis>: Why do I see no call to |
| no_transition in my submachine? </para> |
| <para><emphasis role="underline">Answer</emphasis>: Because of the priority rule defined |
| by UML. It says that in case of transition conflict, the most inner state has a |
| higher priority. So after asking the inner state, the containing composite has to be |
| also asked to handle the transition and could find a possible transition.</para> |
| <para><emphasis role="underline">Question</emphasis>: Why do I get a compile error |
| saying the compiler cannot convert to a function ...Fsm::*(some_event)? </para> |
| <para><emphasis role="underline">Answer</emphasis>: You probably defined a transition |
| triggered by the event some_event, but used a guard/action method taking another |
| event. </para> |
| <para><emphasis role="underline">Question</emphasis>: Why do I get a compile error |
| saying something like “too few” or “too many” template arguments? </para> |
| <para><emphasis role="underline">Answer</emphasis>: You probably defined a transition in |
| form of a a_row or g_row where you wanted just a _row or the other way around. With |
| Row, it could mean that you forgot a "none". </para> |
| <para><emphasis role="underline">Question</emphasis>: Why do I get a very long compile |
| error when I define more than 20 rows in the transition table? </para> |
| <para><emphasis role="underline">Answer</emphasis>: MSM uses Boost.MPL under the hood |
| and this is the default maximum size. Please define the following 3 macros before |
| including any MSM headers: </para> |
| <programlisting>#define BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS |
| #define BOOST_MPL_LIMIT_VECTOR_SIZE 30 // or whatever you need |
| #define BOOST_MPL_LIMIT_MAP_SIZE 30 // or whatever you need </programlisting> |
| <para><emphasis role="underline">Question</emphasis>: Why do I get this error: ”error |
| C2977: 'boost::mpl::vector' : too many template arguments”? </para> |
| <para><emphasis role="underline">Answer</emphasis>: The first possibility is that you |
| defined a transition table as, say, vector17 and have 18 entries. The second is that |
| you have 17 entries and have a composite state. Under the hood, MSM adds a row for |
| every event in the composite transition table. The third one is that you used a |
| mpl::vector without the number of entries but are close to the MPL default of 50 and |
| have a composite, thus pushing you above 50. Then you need mpl/vector60/70….hpp and |
| a mpl/map60/70….hpp </para> |
| <para><emphasis role="underline">Question</emphasis>: Why do I get a very long compile |
| error when I define more than 10 states in a state machine? </para> |
| <para><emphasis role="underline">Answer</emphasis>: MSM uses Boost.Fusion under the hood |
| and this is the default maximum size. Please define the following macro before |
| including any MSM headers: </para> |
| <programlisting>#define FUSION_MAX_VECTOR_SIZE 20 // or whatever you need </programlisting> |
| </chapter> |
| <chapter> |
| <title>Internals</title> |
| <para>This chapter describes the internal machinery of the back-end, which can be useful |
| for UML experts but can be safely ignored for most users. For implementers, the |
| interface between front- and back- end is also described in detail.</para> |
| <sect1> |
| <title><command xml:id="run-to-completion"/>Backend: Run To Completion</title> |
| <para>The back-end implements the following run-to completion algorithm:<itemizedlist> |
| <listitem> |
| <para>Check if one region of the concrete state machine is in a |
| terminate or interrupt state. If yes, event processing is disabled |
| while the condition lasts (forever for a terminate pseudo-state, |
| while active for an interrupt pseudo-state).</para> |
| </listitem> |
| <listitem> |
| <para>If the message queue feature is enabled and if the state machine |
| is already processing an event, push the currently processed event |
| into the queue and end processing. Otherwise, remember that the |
| state machine is now processing an event and continue.</para> |
| </listitem> |
| <listitem> |
| <para>If the state machine detected that no deferred event is used, skip |
| this step. Otherwise, mark the first deferred event from the |
| deferred queue as active.</para> |
| </listitem> |
| <listitem> |
| <para>Now start the core of event dispatching. If exception handling is |
| activated, this will happen inside a try/catch block and the |
| front-end <code>exception_caught</code> is called if an exception |
| occurs. </para> |
| </listitem> |
| <listitem> |
| <para>The event is now dispatched in turn to every region, in the order |
| defined by the initial state front-end definition. This will, for |
| every region, call the corresponding front-end transition definition |
| (the "row" or "Row" of the transition table).</para> |
| </listitem> |
| <listitem> |
| <para>Without transition conflict, if for a given region a transition is |
| possible, the guard condition is checked. If it returns |
| <code>true</code>, the transition processing continues and the |
| current state's exit action is called, followed by the transition |
| action behavior and the new active state's entry behavior.</para> |
| </listitem> |
| <listitem> |
| <para>With transition conflicts (several possible transitions, |
| disambiguated by mutually exclusive guard conditions), the guard |
| conditions are tried in reverse order of their transition definition |
| in the transition table. The first one returning <code>true</code> |
| selects its transition. Note that this is not defined by the UML |
| standard, which simply specifies that if the guard conditions are |
| not mutually exclusive, the state machine is ill-formed and the |
| behaviour undefined. Relying on this implementation-specific |
| behaviour will make it harder for the developer to support another |
| state machine framework.</para> |
| </listitem> |
| <listitem> |
| <para>If at least one region processes the event, this event is seen as |
| having been accepted. If not, the library calls |
| <code>no_transition</code> on the state machine for every |
| contained region.</para> |
| </listitem> |
| <listitem> |
| <para>If the currently active state is a submachine, the behaviour is |
| slightly different. The UML standard specifies that internal |
| transitions have to be tried first, so the event is first dispatched |
| to the submachine. Only if the submachine does not accept the event |
| are other (non internal) transitions tried.</para> |
| </listitem> |
| <listitem> |
| <para>This back-end supports simple states' and submachines' internal |
| transitions. These are provided in the state's |
| <code>internal_transition_table</code> type. Transitions defined |
| in this table are added at the end of the main state machine's |
| transition table, but with a lesser priority than the submachine's |
| transitions (defined in <code>transition_table</code>). This means, |
| for simple states, that these transitions have higher priority than |
| non-internal transitions, conform to the UML standard which gives |
| higher priority to deeper-level transitions. For submachines, this |
| is a non-standard addition which can help make event processing |
| faster by giving a chance to bypass subregion processing. With |
| standard UML, one would need to add a subregion only to process |
| these internal transitions, which would be slower.</para> |
| </listitem> |
| <listitem> |
| <para>After the dispatching itself, the deferred event marked in step 3 |
| (if any) now gets a chance of processing.</para> |
| </listitem> |
| <listitem> |
| <para>Then, events queued in the message queue also get a dispatching |
| chance</para> |
| </listitem> |
| <listitem> |
| <para>Finally, completion / anonymous transitions, if to be found in the |
| transition table, also get their dispatching chance.</para> |
| </listitem> |
| </itemizedlist></para> |
| <para>This algorithm illustrates how the back-end configures itself at compile-time |
| as much as possible. Every feature not found in a given state machine definition |
| is deactivated and has therefore no runtime cost. Completion events, deferred |
| events, terminate states, dispatching to several regions, internal transitions |
| are all deactivated if not used. User configuration is only for exception |
| handling and message queue necessary.</para> |
| </sect1> |
| <sect1> |
| <title><command xml:id="internals-front-back-interface"/>Frontend / Backend |
| interface</title> |
| <para>The design of MSM tries to make front-ends and back-ends (later) to be as |
| interchangeable as possible. Of course, no back-end will ever implement every |
| feature defined by any possible front-end and inversely, but the goal is to make |
| it as easy as possible to extend the current state of the library.</para> |
| <para>To achieve this, MSM divides the functionality between both sides: the |
| front-end is a sort of user interface and is descriptive, the back-end |
| implements the state machine engine.</para> |
| <para>MSM being based on a transition table, a concrete state machine (or a given |
| front-end) must provide a transition_table. This transition table must be made |
| of rows. And each row must tell what kind of transition it is and implement the |
| calls to the actions and guards. A state machine must also define its regions |
| (marked by initial states) And that is about the only constraints for |
| front-ends. How the rows are described is implementer's choice. </para> |
| <para>Every row must provide:</para> |
| <itemizedlist> |
| <listitem> |
| <para>A <code>Source</code> typedef indicating, well, the type of the source |
| state.</para> |
| </listitem> |
| <listitem> |
| <para>A <code>Target</code> typedef indicating, well, the type of the target |
| state.</para> |
| </listitem> |
| <listitem> |
| <para>A <code>Evt</code> typedef indicating the type of the event triggering |
| the transition.</para> |
| </listitem> |
| <listitem> |
| <para>A <code>row_type_tag</code> typedef indicating the type of the |
| transition.</para> |
| </listitem> |
| <listitem> |
| <para>Rows having a type requiring transition actions must provide a static |
| function <code>action_call</code> with the following signature: <code> |
| template <class Fsm,class SourceState,class TargetState,class |
| AllStates> </code></para> |
| <para><code>static void action_call (Fsm& fsm, Event const& evt, |
| SourceState&, TargetState&, AllStates&) </code></para> |
| <para>The function gets as parameters the (back-end) state machine, the |
| event, source and target states and a container (in the current |
| back-end, a fusion::set) of all the states defined in the state machine. |
| For example, as the back-end has the front-end as basic class, |
| <code>action_call</code> is simply defined as |
| <code>(fsm.*action)(evt)</code>.</para> |
| </listitem> |
| <listitem> |
| <para>Rows having a type requiring a guard must provide a static function |
| <code>guard_call</code> with the following signature:<code |
| > </code></para> |
| <para><code>template <class Fsm,class SourceState,class TargetState,class |
| AllStates></code></para> |
| <para><code>static bool guard_call (Fsm&, Event const&, |
| SourceState&, TargetState&, AllStates&)</code></para> |
| </listitem> |
| <listitem> |
| <para>The possible transition (row) types are:<itemizedlist> |
| <listitem> |
| <para>a_row_tag: a transition with actions and no guard</para> |
| </listitem> |
| <listitem> |
| <para>g_row_type: a transition with a guard and no |
| actions</para> |
| </listitem> |
| <listitem> |
| <para>_row_tag: a transition without actions or guard</para> |
| </listitem> |
| <listitem> |
| <para>row_tag: a transition with guard and actions</para> |
| </listitem> |
| <listitem> |
| <para>a_irow_tag: an internal transition (defined inside the |
| <code>transition_table</code>) with actions</para> |
| </listitem> |
| <listitem> |
| <para>g_irow_tag: an internal transition (defined inside the |
| <code>transition_table</code>) with guard</para> |
| </listitem> |
| <listitem> |
| <para>irow_tag: an internal transition (defined inside the |
| <code>transition_table</code>) with actions and |
| guards</para> |
| </listitem> |
| <listitem> |
| <para>_irow_tag: an internal transition (defined inside the |
| <code>transition_table</code>) without action or guard. |
| Due to higher priority for internal transitions, this is |
| equivalent to a "ignore event"</para> |
| </listitem> |
| <listitem> |
| <para>sm_a_i_row_tag: an internal transition (defined inside the |
| <code>internal_transition_table</code>) with |
| actions</para> |
| </listitem> |
| <listitem> |
| <para>sm_g_i_row_tag: an internal transition (defined inside the |
| <code>internal_transition_table</code>) with |
| guard</para> |
| </listitem> |
| <listitem> |
| <para>sm_i_row_tag: an internal transition (defined inside the |
| <code>internal_transition_table</code>) with actions and |
| guards</para> |
| </listitem> |
| <listitem> |
| <para>sm__i_row_tag: an internal transition (defined inside the |
| <code>internal_transition_table</code>) without action |
| or guard. Due to higher priority for internal transitions, |
| this is quivalent to a "ignore event"</para> |
| </listitem> |
| </itemizedlist></para> |
| </listitem> |
| </itemizedlist> |
| <para>Furthermore, a front-end must provide the definition of states and state |
| machines. State machine definitions must provide (the implementer is free to |
| provide it or let it be done by every concrete state machine. Different MSM |
| front-ends took one or the other approach):<itemizedlist> |
| <listitem> |
| <para><code>initial_state</code>: This typedef can be a single state or |
| a mpl container and provides the initial states defining one or |
| several orthogonal regions.</para> |
| </listitem> |
| <listitem> |
| <para><code>transition_table</code>: This typedef is a MPL sequence of |
| transition rows.</para> |
| </listitem> |
| <listitem> |
| <para><code>configuration</code>: this typedef is a MPL sequence of |
| known types triggering special behavior in the back-end, for example |
| if a concrete fsm requires a message queue or exception |
| catching.</para> |
| </listitem> |
| </itemizedlist></para> |
| <para>States and state machines must both provide a (possibly empty) definition of:<itemizedlist> |
| <listitem> |
| <para><code>flag_list</code>: the flags being active when this state or |
| state machine become the current state of the fsm.</para> |
| </listitem> |
| <listitem> |
| <para><code>deferred_events</code>: events being automatically deferred |
| when the state is the current state of the fsm.</para> |
| </listitem> |
| <listitem> |
| <para><code>internal_transition_table</code>: the internal transitions |
| of this state.</para> |
| </listitem> |
| <listitem> |
| <para><code>on_entry</code> and <code>on_exit</code> methods.</para> |
| </listitem> |
| </itemizedlist></para> |
| </sect1> |
| <sect1> |
| <title><command xml:id="internals-state-id"/> Generated state ids </title> |
| <para>Normally, one does not need to know the ids are generated for all the states |
| of a state machine, unless for debugging purposes, like the pstate function does |
| in the tutorials in order to display the name of the current state. This section |
| will show how to automatically display typeid-generated names, but these are not |
| very readable on all platforms, so it can help to know how the ids are |
| generated. The ids are generated using the transition table, from the “Start” |
| column up to down, then from the “Next” column, up to down, as shown in the next |
| image: </para> |
| <para><inlinemediaobject> |
| <imageobject> |
| <imagedata fileref="images/AnnexA.jpg" width="90%" scalefit="1"/> |
| </imageobject> |
| </inlinemediaobject></para> |
| <para>Stopped will get id 0, Open id 1, ErrorMode id 6 and SleepMode (seen only in |
| the “Next” column) id 7. If you have some implicitly created states, like |
| transition-less initial states or states created using the explicit_creation |
| typedef, these will be added as a source at the end of the transition table. If |
| you have submachine states, a row will be added for them at the end of the |
| table, after the automatically or explicitly created states, which can change |
| their id. The next help you will need for debugging would be to call the |
| current_state method of the state_machine class, then the display_type helper to |
| generate a readable name from the id. If you do not want to go through the |
| transition table to fill an array of names, the library provides another helper, |
| fill_state_names, which, given an array of sufficient size (please see next |
| section to know how many states are defined in the state machine), will fill it |
| with typeid-generated names. </para> |
| </sect1> |
| <sect1> |
| <title>Metaprogramming tools</title> |
| <para>We can find for the transition table more uses than what we have seen so far. |
| Let's suppose you need to write a coverage tool. A state machine would be |
| perfect for such a job, if only it could provide some information about its |
| structure. Thanks to the transition table and Boost.MPL, it does.</para> |
| <para>What is needed for a coverage tool? You need to know how many states are |
| defined in the state machine, and how many events can be fired. This way you can |
| log the fired events and the states visited in the life of a concrete machine |
| and be able to perform some coverage analysis, like “fired 65% of all possible |
| events and visited 80% of the states defined in the state machine”. To achieve |
| this, MSM provides a few useful tools:<itemizedlist> |
| <listitem> |
| <para>generate_state_set<transition table>: returns a mpl::set of all |
| the states defined in the table.</para> |
| </listitem> |
| <listitem> |
| <para>generate_event_set<transition table>: returns a mpl::set of all |
| the events defined in the table.</para> |
| </listitem> |
| <listitem> |
| <para>using mpl::size<>::value you can get the number of elements in |
| the set.</para> |
| </listitem> |
| <listitem> |
| <para>display_type defines an operator() sending typeid(Type).name() to |
| cout.</para> |
| </listitem> |
| <listitem> |
| <para>fill_state_names fills an array of char const* with names of all |
| states (found by typeid)</para> |
| </listitem> |
| <listitem> |
| <para>using mpl::for_each on the result of generate_state_set and |
| generate_event_set passing display_type as argument will display all |
| the states of the state machine.</para> |
| </listitem> |
| <listitem> |
| <para>let's suppose you need to recursively find the states and events |
| defined in the composite states and thus also having a transition |
| table. Calling recursive_get_transition_table<Composite> will |
| return you the transition table of the composite state, recursively |
| adding the transition tables of all sub-state machines and |
| sub-sub...-sub-state machines. Then call generate_state_set or |
| generate_event_set on the result to get the full list of states and |
| events. </para> |
| </listitem> |
| </itemizedlist></para> |
| <para> An <link xlink:href="examples/BoostCon09Full.cpp">example</link> shows the |
| tools in action. </para> |
| </sect1> |
| </chapter> |
| <chapter> |
| <title>Acknowledgements</title> |
| <para>I am in debt to the following people who helped MSM along the way.</para> |
| <sect1> |
| <title>MSM v2</title> |
| <para> |
| <itemizedlist> |
| <listitem> |
| <para>Thanks to Dave Abrahams for managing the review</para> |
| </listitem> |
| <listitem> |
| <para>Thanks to Eric Niebler for his patience correcting my grammar |
| errors</para> |
| </listitem> |
| <listitem> |
| <para>Special thanks to Joel de Guzman who gave me very good ideas at |
| the BoostCon09. These ideas were the starting point of the redesign. |
| Any time again, Joel ☺</para> |
| </listitem> |
| <listitem> |
| <para>Thanks to Richard O’Hara for making Green Hills bring a patch in |
| less than 1 week, thus adding one more compiler to the supported |
| list.</para> |
| </listitem> |
| <listitem> |
| <para>Big thanks to those who took the time to write a review: Franz |
| Alt, David Bergman, Michael Caisse, Barend Gehrels, Darryl Greene, |
| Juraj Ivancic, Erik Nelson, Kenny Riddile.</para> |
| </listitem> |
| <listitem> |
| <para>Thanks to Matt Calabrese, Juraj Ivancic, Adam Merz and Joseph Wu |
| for reporting bugs.</para> |
| </listitem> |
| </itemizedlist> |
| </para> |
| </sect1> |
| <sect1> |
| <title> MSM v1</title> |
| <para> |
| <itemizedlist> |
| <listitem> |
| <para>The original version of this framework is based on the brilliant |
| work of David Abrahams and Aleksey Gurtovoy who laid down the base |
| and the principles of the framework in their excellent book, “C++ |
| template Metaprogramming”. The implementation also makes heavy use |
| of the boost::mpl.</para> |
| </listitem> |
| <listitem> |
| <para>Thanks to Jeff Flinn for his idea of the user-defined base state |
| and his review which allowed MSM to be presented at the |
| BoostCon09.</para> |
| </listitem> |
| <listitem> |
| <para>Thanks to my MSM v1 beta testers, Christoph Woskowski and Franz |
| Alt for using the framework with little documentation and to my |
| private reviewer, Edouard Alligand</para> |
| </listitem> |
| </itemizedlist> |
| </para> |
| </sect1> |
| </chapter> |
| <chapter> |
| <title>Version history</title> |
| <sect1> |
| <title>From V2.10 to V2.12</title> |
| <para> |
| <itemizedlist> |
| <listitem> |
| <para>Support for <command xlink:href="#back-end-serialization">serialization</command></para> |
| </listitem> |
| <listitem> |
| <para><command xlink:href="#eUML-reuse-functor">Possibility to use |
| normal functors</command> (from functor front-end) in |
| eUML.</para> |
| </listitem> |
| <listitem> |
| <para><command xlink:href="#backend-fsm-constructor-args">New constructors</command> where substates / submachines can be taken as |
| arguments. This allows passing arguments to the constructor of a |
| submachine.</para> |
| </listitem> |
| <listitem> |
| <para>Bugfixes</para> |
| </listitem> |
| </itemizedlist> |
| </para> |
| </sect1> |
| <sect1> |
| <title>From V2.0 to V2.12</title> |
| <para> |
| <itemizedlist> |
| <listitem> |
| <para>New documentation</para> |
| </listitem> |
| <listitem> |
| <para>Internal transitions. Either as part of the transition table or |
| using a state's internal transition table</para> |
| </listitem> |
| <listitem> |
| <para>increased dispatch and copy speed</para> |
| </listitem> |
| <listitem> |
| <para><command xlink:href="#basic-row2">new row types</command> for the |
| basic front-end</para> |
| </listitem> |
| <listitem> |
| <para>new eUML syntax, better attribute support, macros to ease |
| developer's life. Even VC8 seems to like it better.</para> |
| </listitem> |
| <listitem> |
| <para>New policy for reduced compile-time at the cost of dispatch |
| speed</para> |
| </listitem> |
| <listitem> |
| <para>Support for base events</para> |
| </listitem> |
| <listitem> |
| <para>possibility to choose the initial event</para> |
| </listitem> |
| </itemizedlist> |
| </para> |
| </sect1> |
| </chapter> |
| </part> |
| <part> |
| <title><command xml:id="Reference-begin"/>Reference</title> |
| <chapter> |
| <title>eUML operators and basic helpers</title> |
| <para>The following table lists the supported operators: </para> |
| <para> |
| <table frame="all"> |
| <title>Operators and state machine helpers</title> |
| <tgroup cols="3"> |
| <colspec colname="c1" colnum="1"/> |
| <colspec colname="c2" colnum="2"/> |
| <colspec colname="c3" colnum="3"/> |
| <thead> |
| <row> |
| <entry>eUML function / operator</entry> |
| <entry>Description</entry> |
| <entry>Functor</entry> |
| </row> |
| </thead> |
| <tbody> |
| <row> |
| <entry>&&</entry> |
| <entry>Calls lazily Action1&& Action2</entry> |
| <entry>And_</entry> |
| </row> |
| <row> |
| <entry>||</entry> |
| <entry>Calls lazily Action1|| Action2</entry> |
| <entry>Or_</entry> |
| </row> |
| <row> |
| <entry>!</entry> |
| <entry>Calls lazily !Action1</entry> |
| <entry>Not_</entry> |
| </row> |
| <row> |
| <entry>!=</entry> |
| <entry>Calls lazily Action1 != Action2</entry> |
| <entry>NotEqualTo_</entry> |
| </row> |
| <row> |
| <entry>==</entry> |
| <entry>Calls lazily Action1 == Action2</entry> |
| <entry>EqualTo_</entry> |
| </row> |
| <row> |
| <entry>></entry> |
| <entry>Calls lazily Action1 > Action2</entry> |
| <entry>Greater_</entry> |
| </row> |
| <row> |
| <entry>>=</entry> |
| <entry>Calls lazily Action1 >= Action2</entry> |
| <entry>Greater_Equal_</entry> |
| </row> |
| <row> |
| <entry><</entry> |
| <entry>Calls lazily Action1 < Action2</entry> |
| <entry>Less_</entry> |
| </row> |
| <row> |
| <entry><=</entry> |
| <entry>Calls lazily Action1 <= Action2</entry> |
| <entry>Less_Equal_</entry> |
| </row> |
| <row> |
| <entry>&</entry> |
| <entry>Calls lazily Action1 & Action2</entry> |
| <entry>Bitwise_And_</entry> |
| </row> |
| <row> |
| <entry>|</entry> |
| <entry>Calls lazily Action1 | Action2</entry> |
| <entry>Bitwise_Or_</entry> |
| </row> |
| <row> |
| <entry>^</entry> |
| <entry>Calls lazily Action1 ^ Action2</entry> |
| <entry>Bitwise_Xor_</entry> |
| </row> |
| <row> |
| <entry>--</entry> |
| <entry>Calls lazily --Action1 / Action1--</entry> |
| <entry>Pre_Dec_ / Post_Dec_</entry> |
| </row> |
| <row> |
| <entry>++</entry> |
| <entry>Calls lazily ++Action1 / Action1++</entry> |
| <entry>Pre_Inc_ / Post_Inc_</entry> |
| </row> |
| <row> |
| <entry>/</entry> |
| <entry>Calls lazily Action1 / Action2</entry> |
| <entry>Divides_</entry> |
| </row> |
| <row> |
| <entry>/=</entry> |
| <entry>Calls lazily Action1 /= Action2</entry> |
| <entry>Divides_Assign_</entry> |
| </row> |
| <row> |
| <entry>*</entry> |
| <entry>Calls lazily Action1 * Action2</entry> |
| <entry>Multiplies_</entry> |
| </row> |
| <row> |
| <entry>*=</entry> |
| <entry>Calls lazily Action1 *= Action2</entry> |
| <entry>Multiplies_Assign_</entry> |
| </row> |
| <row> |
| <entry>+ (binary)</entry> |
| <entry>Calls lazily Action1 + Action2</entry> |
| <entry>Plus_</entry> |
| </row> |
| <row> |
| <entry>+ (unary)</entry> |
| <entry>Calls lazily +Action1</entry> |
| <entry>Unary_Plus_</entry> |
| </row> |
| <row> |
| <entry>+=</entry> |
| <entry>Calls lazily Action1 += Action2</entry> |
| <entry>Plus_Assign_</entry> |
| </row> |
| <row> |
| <entry>- (binary)</entry> |
| <entry>Calls lazily Action1 - Action2</entry> |
| <entry>Minus_</entry> |
| </row> |
| <row> |
| <entry>- (unary)</entry> |
| <entry>Calls lazily -Action1</entry> |
| <entry>Unary_Minus_</entry> |
| </row> |
| <row> |
| <entry>-=</entry> |
| <entry>Calls lazily Action1 -= Action2</entry> |
| <entry>Minus_Assign_</entry> |
| </row> |
| <row> |
| <entry>%</entry> |
| <entry>Calls lazily Action1 % Action2</entry> |
| <entry>Modulus_</entry> |
| </row> |
| <row> |
| <entry>%=</entry> |
| <entry>Calls lazily Action1 %= Action2</entry> |
| <entry>Modulus_Assign_</entry> |
| </row> |
| <row> |
| <entry>>></entry> |
| <entry>Calls lazily Action1 >> Action2</entry> |
| <entry>ShiftRight_</entry> |
| </row> |
| <row> |
| <entry>>>=</entry> |
| <entry>Calls lazily Action1 >>= Action2</entry> |
| <entry>ShiftRight_Assign_</entry> |
| </row> |
| <row> |
| <entry><<</entry> |
| <entry>Calls lazily Action1 << Action2</entry> |
| <entry>ShiftLeft_</entry> |
| </row> |
| <row> |
| <entry><<=</entry> |
| <entry>Calls lazily Action1 <<= Action2</entry> |
| <entry>ShiftLeft_Assign_</entry> |
| </row> |
| <row> |
| <entry>[] (works on vector, map, arrays)</entry> |
| <entry>Calls lazily Action1 [Action2]</entry> |
| <entry>Subscript_</entry> |
| </row> |
| <row> |
| <entry>if_then_else_(Condition,Action1,Action2)</entry> |
| <entry>Returns either the result of calling Action1 or the result of |
| calling Action2</entry> |
| <entry>If_Else_</entry> |
| </row> |
| <row> |
| <entry>if_then_(Condition,Action)</entry> |
| <entry>Returns the result of calling Action if Condition</entry> |
| <entry>If_Then_</entry> |
| </row> |
| <row> |
| <entry>while_(Condition, Body)</entry> |
| <entry>While Condition(), calls Body(). Returns nothing</entry> |
| <entry>While_Do_</entry> |
| </row> |
| <row> |
| <entry>do_while_(Condition, Body)</entry> |
| <entry>Calls Body() while Condition(). Returns nothing</entry> |
| <entry>Do_While_</entry> |
| </row> |
| <row> |
| <entry>for_(Begin,Stop,EndLoop,Body)</entry> |
| <entry>Calls for(Begin;Stop;EndLoop){Body;}</entry> |
| <entry>For_Loop_</entry> |
| </row> |
| <row> |
| <entry>process_(Event [,fsm1] [,fsm2] [,fsm3] [,fsm4])</entry> |
| <entry>Processes Event on the current state machine (if no fsm |
| specified) or on up to 4 state machines returned by an |
| appropriate functor.</entry> |
| <entry>Process_</entry> |
| </row> |
| <row> |
| <entry>process2_(Event, Data [,fsm1] [,fsm2] [,fsm3])</entry> |
| <entry>Processes Event on the current state machine (if no fsm |
| specified) or on up to 2 state machines returned by an |
| appropriate functor. The event is copy-constructed from what |
| Data() returns.</entry> |
| <entry>Process2_</entry> |
| </row> |
| <row> |
| <entry>is_flag_(Flag [,fsm])</entry> |
| <entry>Calls is_flag_active() on the current state machine or the |
| one returned by calling fsm.</entry> |
| <entry>Get_Flag_</entry> |
| </row> |
| <row> |
| <entry>event_ [(attribute name)]</entry> |
| <entry>Returns the current event (as const reference)</entry> |
| <entry>GetEvent_</entry> |
| </row> |
| <row> |
| <entry>source_ [(attribute name)]</entry> |
| <entry>Returns the source state of the currently triggered |
| transition (as reference). If an attribute name is provided, |
| returns the attribute by reference.</entry> |
| <entry>GetSource_</entry> |
| </row> |
| <row> |
| <entry>target_ [(attribute name)]</entry> |
| <entry>Returns the target state of the currently triggered |
| transition (as reference). If an attribute name is provided, |
| returns the attribute by reference.</entry> |
| <entry>GetTarget_</entry> |
| </row> |
| <row> |
| <entry>state_ [(attribute name)]</entry> |
| <entry>Returns the source state of the currently active state (as |
| reference). Valid inside a state entry/exit action. If an |
| attribute name is provided, returns the attribute by |
| reference.</entry> |
| <entry>GetState_</entry> |
| </row> |
| <row> |
| <entry>fsm_ [(attribute name)]</entry> |
| <entry>Returns the current state machine (as reference). Valid |
| inside a state entry/exit action or a transition. If an |
| attribute name is provided, returns the attribute by |
| reference.</entry> |
| <entry>GetFsm_</entry> |
| </row> |
| <row> |
| <entry>substate_(state_name [,fsm])</entry> |
| <entry>Returns (as reference) the state state_name referenced in the |
| current state machine or the one given as argument.</entry> |
| <entry>SubState_</entry> |
| </row> |
| </tbody> |
| </tgroup> |
| </table> |
| </para> |
| <para>To use these functions, you need to include: </para> |
| <para><code>#include <msm/front/euml/euml.hpp></code></para> |
| </chapter> |
| <chapter> |
| <title> |
| <command xml:id="eUML-STL-all"/>Functional programming </title> |
| <para>To use these functions, you need to include: </para> |
| <para><code>#include <msm/front/euml/stl.hpp></code></para> |
| <para>or the specified header in the following tables.</para> |
| <para>The following tables list the supported STL algorithms: </para> |
| <para> |
| <command xml:id="eUML-STL-querying"/> |
| <table frame="all"> |
| <title>STL algorithms</title> |
| <tgroup cols="2"> |
| <colspec colname="c2" colnum="1"/> |
| <colspec colname="c3" colnum="2"/> |
| <thead> |
| <row> |
| <entry>STL algorithms in querying.hpp</entry> |
| <entry>Functor</entry> |
| </row> |
| </thead> |
| <tbody> |
| <row> |
| <entry>find_(first, last, value)</entry> |
| <entry>Find_</entry> |
| </row> |
| <row> |
| <entry>find_if_(first, last, value)</entry> |
| <entry>FindIf_</entry> |
| </row> |
| <row> |
| <entry>lower_bound_(first, last, value [,opᵃ])</entry> |
| <entry>LowerBound_</entry> |
| </row> |
| <row> |
| <entry>upper_bound_(first, last, value [,opᵃ])</entry> |
| <entry>UpperBound_</entry> |
| </row> |
| <row> |
| <entry>equal_range_(first, last, value [,opᵃ])</entry> |
| <entry>EqualRange_</entry> |
| </row> |
| <row> |
| <entry>binary_search_(first, last, value [,opᵃ])</entry> |
| <entry>BinarySearch_</entry> |
| </row> |
| <row> |
| <entry>min_element_(first, last[,opᵃ])</entry> |
| <entry>MinElement_</entry> |
| </row> |
| <row> |
| <entry>max_element_(first, last[,opᵃ])</entry> |
| <entry>MaxElement_</entry> |
| </row> |
| <row> |
| <entry>adjacent_find_(first, last[,opᵃ])</entry> |
| <entry>AdjacentFind_</entry> |
| </row> |
| <row> |
| <entry>find_end_( first1, last1, first2, last2 [,op ᵃ])</entry> |
| <entry>FindEnd_</entry> |
| </row> |
| <row> |
| <entry>find_first_of_( first1, last1, first2, last2 [,op ᵃ])</entry> |
| <entry>FindFirstOf_</entry> |
| </row> |
| <row> |
| <entry>equal_( first1, last1, first2 [,op ᵃ])</entry> |
| <entry>Equal_</entry> |
| </row> |
| <row> |
| <entry>search_( first1, last1, first2, last2 [,op ᵃ])</entry> |
| <entry>Search_</entry> |
| </row> |
| <row> |
| <entry>includes_( first1, last1, first2, last2 [,op ᵃ])</entry> |
| <entry>Includes_</entry> |
| </row> |
| <row> |
| <entry>lexicographical_compare_ ( first1, last1, first2, last2 [,op |
| ᵃ]) </entry> |
| <entry>LexicographicalCompare_</entry> |
| </row> |
| <row> |
| <entry>count_(first, last, value [,size])</entry> |
| <entry>Count_</entry> |
| </row> |
| <row> |
| <entry>count_if_(first, last, op ᵃ [,size])</entry> |
| <entry>CountIf_</entry> |
| </row> |
| <row> |
| <entry>distance_(first, last)</entry> |
| <entry>Distance_</entry> |
| </row> |
| <row> |
| <entry>mismatch _( first1, last1, first2 [,op ᵃ])</entry> |
| <entry>Mismatch_</entry> |
| </row> |
| </tbody> |
| </tgroup> |
| </table> |
| </para> |
| <para> |
| <command xml:id="eUML-STL-iteration"/> |
| <table frame="all"> |
| <title>STL algorithms</title> |
| <tgroup cols="2"> |
| <colspec colname="c2" colnum="1"/> |
| <colspec colname="c3" colnum="2"/> |
| <thead> |
| <row> |
| <entry>STL algorithms in iteration.hpp</entry> |
| <entry>Functor</entry> |
| </row> |
| </thead> |
| <tbody> |
| <row> |
| <entry>for_each_(first,last, unary opᵃ)</entry> |
| <entry>ForEach_</entry> |
| </row> |
| <row> |
| <entry>accumulate_first, last, init [,opᵃ])</entry> |
| <entry>Accumulate_</entry> |
| </row> |
| </tbody> |
| </tgroup> |
| </table> |
| </para> |
| <para> |
| <command xml:id="eUML-STL-transformation"/> |
| <table> |
| <title>STL algorithms</title> |
| <tgroup cols="2"> |
| <colspec colname="c2" colnum="1"/> |
| <colspec colname="c3" colnum="2"/> |
| <thead> |
| <row> |
| <entry>STL algorithms in transformation.hpp</entry> |
| <entry>Functor</entry> |
| </row> |
| </thead> |
| <tbody> |
| <row> |
| <entry>copy_(first, last, result)</entry> |
| <entry>Copy_</entry> |
| </row> |
| <row> |
| <entry>copy_backward_(first, last, result)</entry> |
| <entry>CopyBackward_</entry> |
| </row> |
| <row> |
| <entry>reverse_(first, last)</entry> |
| <entry>Reverse_</entry> |
| </row> |
| <row> |
| <entry>reverse_copy_(first, last , result)</entry> |
| <entry>ReverseCopy_</entry> |
| </row> |
| <row> |
| <entry>remove_(first, last, value)</entry> |
| <entry>Remove_</entry> |
| </row> |
| <row> |
| <entry>remove_if_(first, last , opᵃ)</entry> |
| <entry>RemoveIf_</entry> |
| </row> |
| <row> |
| <entry>remove_copy_(first, last , output, value)</entry> |
| <entry>RemoveCopy_</entry> |
| </row> |
| <row> |
| <entry>remove_copy_if_(first, last, output, opᵃ)</entry> |
| <entry>RemoveCopyIf_</entry> |
| </row> |
| <row> |
| <entry>fill_(first, last, value)</entry> |
| <entry>Fill_</entry> |
| </row> |
| <row> |
| <entry>fill_n_(first, size, value)ᵇ</entry> |
| <entry>FillN_</entry> |
| </row> |
| <row> |
| <entry>generate_(first, last, generatorᵃ)</entry> |
| <entry>Generate_</entry> |
| </row> |
| <row> |
| <entry>generate_(first, size, generatorᵃ)ᵇ</entry> |
| <entry>GenerateN_</entry> |
| </row> |
| <row> |
| <entry>unique_(first, last [,opᵃ])</entry> |
| <entry>Unique_</entry> |
| </row> |
| <row> |
| <entry>unique_copy_(first, last, output [,opᵃ])</entry> |
| <entry>UniqueCopy_</entry> |
| </row> |
| <row> |
| <entry>random_shuffle_(first, last [,opᵃ])</entry> |
| <entry>RandomShuffle_</entry> |
| </row> |
| <row> |
| <entry>rotate_copy_(first, middle, last, output)</entry> |
| <entry>RotateCopy_</entry> |
| </row> |
| <row> |
| <entry>partition_ (first, last [,opᵃ])</entry> |
| <entry>Partition_</entry> |
| </row> |
| <row> |
| <entry>stable_partition_ (first, last [,opᵃ])</entry> |
| <entry>StablePartition_</entry> |
| </row> |
| <row> |
| <entry>stable_sort_(first, last [,opᵃ])</entry> |
| <entry>StableSort_</entry> |
| </row> |
| <row> |
| <entry>sort_(first, last [,opᵃ])</entry> |
| <entry>Sort_</entry> |
| </row> |
| <row> |
| <entry>partial_sort_(first, middle, last [,opᵃ])</entry> |
| <entry>PartialSort_</entry> |
| </row> |
| <row> |
| <entry>partial_sort_copy_ (first, last, res_first, res_last [,opᵃ]) </entry> |
| <entry>PartialSortCopy_</entry> |
| </row> |
| <row> |
| <entry>nth_element_(first, nth, last [,opᵃ])</entry> |
| <entry>NthElement_</entry> |
| </row> |
| <row> |
| <entry>merge_( first1, last1, first2, last2, output [,op ᵃ])</entry> |
| <entry>Merge_</entry> |
| </row> |
| <row> |
| <entry>inplace_merge_(first, middle, last [,opᵃ])</entry> |
| <entry>InplaceMerge_</entry> |
| </row> |
| <row> |
| <entry>set_union_(first1, last1, first2, last2, output [,op |
| ᵃ])</entry> |
| <entry>SetUnion_</entry> |
| </row> |
| <row> |
| <entry>push_heap_(first, last [,op ᵃ])</entry> |
| <entry>PushHeap_</entry> |
| </row> |
| <row> |
| <entry>pop_heap_(first, last [,op ᵃ])</entry> |
| <entry>PopHeap_</entry> |
| </row> |
| <row> |
| <entry>make_heap_(first, last [,op ᵃ])</entry> |
| <entry>MakeHeap_</entry> |
| </row> |
| <row> |
| <entry>sort_heap_(first, last [,op ᵃ])</entry> |
| <entry>SortHeap_</entry> |
| </row> |
| <row> |
| <entry>next_permutation_(first, last [,op ᵃ])</entry> |
| <entry>NextPermutation_</entry> |
| </row> |
| <row> |
| <entry>prev_permutation_(first, last [,op ᵃ])</entry> |
| <entry>PrevPermutation_</entry> |
| </row> |
| <row> |
| <entry>inner_product_(first1, last1, first2, init [,op1ᵃ] [,op2ᵃ]) </entry> |
| <entry>InnerProduct_</entry> |
| </row> |
| <row> |
| <entry>partial_sum_(first, last, output [,opᵃ])</entry> |
| <entry>PartialSum_</entry> |
| </row> |
| <row> |
| <entry>adjacent_difference_(first, last, output [,opᵃ])</entry> |
| <entry>AdjacentDifference_</entry> |
| </row> |
| <row> |
| <entry>replace_(first, last, old_value, new_value)</entry> |
| <entry>Replace_</entry> |
| </row> |
| <row> |
| <entry>replace_if_(first, last, opᵃ, new_value)</entry> |
| <entry>ReplaceIf_</entry> |
| </row> |
| <row> |
| <entry>replace_copy_(first, last, result, old_value, |
| new_value)</entry> |
| <entry>ReplaceCopy_</entry> |
| </row> |
| <row> |
| <entry>replace_copy_if_(first, last, result, opᵃ, new_value)</entry> |
| <entry>ReplaceCopyIf_</entry> |
| </row> |
| <row> |
| <entry>rotate_(first, middle, last)ᵇ</entry> |
| <entry>Rotate_</entry> |
| </row> |
| </tbody> |
| </tgroup> |
| </table> |
| </para> |
| <para> |
| <command xml:id="eUML-STL-container"/> |
| <table> |
| <title>STL container methods</title> |
| <tgroup cols="2"> |
| <colspec colname="c2" colnum="1"/> |
| <colspec colname="c3" colnum="2"/> |
| <thead> |
| <row> |
| <entry>STL container methods(common) in container.hpp</entry> |
| <entry>Functor</entry> |
| </row> |
| </thead> |
| <tbody> |
| <row> |
| <entry>container::reference front_(container)</entry> |
| <entry>Front_</entry> |
| </row> |
| <row> |
| <entry>container::reference back_(container)</entry> |
| <entry>Back_</entry> |
| </row> |
| <row> |
| <entry>container::iterator begin_(container)</entry> |
| <entry>Begin_</entry> |
| </row> |
| <row> |
| <entry>container::iterator end_(container)</entry> |
| <entry>End_</entry> |
| </row> |
| <row> |
| <entry>container::reverse_iterator rbegin_(container)</entry> |
| <entry>RBegin_</entry> |
| </row> |
| <row> |
| <entry>container::reverse_iterator rend_(container)</entry> |
| <entry>REnd_</entry> |
| </row> |
| <row> |
| <entry>void push_back_(container, value)</entry> |
| <entry>Push_Back_</entry> |
| </row> |
| <row> |
| <entry>void pop_back_(container, value)</entry> |
| <entry>Pop_Back_</entry> |
| </row> |
| <row> |
| <entry>void push_front_(container, value)</entry> |
| <entry>Push_Front_</entry> |
| </row> |
| <row> |
| <entry>void pop_front_(container, value)</entry> |
| <entry>Pop_Front_</entry> |
| </row> |
| <row> |
| <entry>void clear_(container)</entry> |
| <entry>Clear_</entry> |
| </row> |
| <row> |
| <entry>size_type capacity_(container)</entry> |
| <entry>Capacity_</entry> |
| </row> |
| <row> |
| <entry>size_type size_(container)</entry> |
| <entry>Size_</entry> |
| </row> |
| <row> |
| <entry>size_type max_size_(container)</entry> |
| <entry>Max_Size_</entry> |
| </row> |
| <row> |
| <entry>void reserve_(container, value)</entry> |
| <entry>Reserve _</entry> |
| </row> |
| <row> |
| <entry>void resize_(container, value)</entry> |
| <entry>Resize _</entry> |
| </row> |
| <row> |
| <entry>iterator insert_(container, pos, value)</entry> |
| <entry>Insert_</entry> |
| </row> |
| <row> |
| <entry>void insert_( container , pos, first, last)</entry> |
| <entry>Insert_</entry> |
| </row> |
| <row> |
| <entry>void insert_( container , pos, number, value)</entry> |
| <entry>Insert_</entry> |
| </row> |
| <row> |
| <entry>void swap_( container , other_container)</entry> |
| <entry>Swap_</entry> |
| </row> |
| <row> |
| <entry>void erase_( container , pos)</entry> |
| <entry>Erase_</entry> |
| </row> |
| <row> |
| <entry>void erase_( container , first, last) </entry> |
| <entry>Erase_</entry> |
| </row> |
| <row> |
| <entry>bool empty_( container)</entry> |
| <entry>Empty_</entry> |
| </row> |
| </tbody> |
| </tgroup> |
| </table> |
| </para> |
| <para> |
| <table> |
| <title>STL list methods</title> |
| <tgroup cols="2"> |
| <colspec colname="c2" colnum="1"/> |
| <colspec colname="c3" colnum="2"/> |
| <thead> |
| <row> |
| <entry>std::list methods in container.hpp</entry> |
| <entry>Functor</entry> |
| </row> |
| </thead> |
| <tbody> |
| <row> |
| <entry>void list_remove_(container, value)</entry> |
| <entry>ListRemove_</entry> |
| </row> |
| <row> |
| <entry>void list_remove_if_(container, opᵃ)</entry> |
| <entry>ListRemove_If_</entry> |
| </row> |
| <row> |
| <entry>void list_merge_(container, other_list)</entry> |
| <entry>ListMerge_</entry> |
| </row> |
| <row> |
| <entry>void list_merge_(container, other_list, opᵃ)</entry> |
| <entry>ListMerge_</entry> |
| </row> |
| <row> |
| <entry>void splice_(container, iterator, other_list)</entry> |
| <entry>Splice_</entry> |
| </row> |
| <row> |
| <entry>void splice_(container, iterator, other_list, |
| iterator)</entry> |
| <entry>Splice_</entry> |
| </row> |
| <row> |
| <entry>void splice_(container, iterator, other_list, first, |
| last)</entry> |
| <entry>Splice_</entry> |
| </row> |
| <row> |
| <entry>void list_reverse_(container)</entry> |
| <entry>ListReverse_</entry> |
| </row> |
| <row> |
| <entry>void list_unique_(container)</entry> |
| <entry>ListUnique_</entry> |
| </row> |
| <row> |
| <entry>void list_unique_(container, opᵃ)</entry> |
| <entry>ListUnique_</entry> |
| </row> |
| <row> |
| <entry>void list_sort_(container)</entry> |
| <entry>ListSort_</entry> |
| </row> |
| <row> |
| <entry>void list_sort_(container, opᵃ)</entry> |
| <entry>ListSort_</entry> |
| </row> |
| </tbody> |
| </tgroup> |
| </table> |
| </para> |
| <para> |
| <table> |
| <title>STL associative container methods </title> |
| <tgroup cols="2"> |
| <colspec colname="c2" colnum="1"/> |
| <colspec colname="c3" colnum="2"/> |
| <thead> |
| <row> |
| <entry>Associative container methods in container.hpp</entry> |
| <entry>Functor</entry> |
| </row> |
| </thead> |
| <tbody> |
| <row> |
| <entry>iterator insert_(container, pos, value)</entry> |
| <entry>Insert_</entry> |
| </row> |
| <row> |
| <entry>void insert_( container , first, last)</entry> |
| <entry>Insert_</entry> |
| </row> |
| <row> |
| <entry>pair<iterator, bool> insert_( container , value)</entry> |
| <entry>Insert_</entry> |
| </row> |
| <row> |
| <entry>void associative_erase_( container , pos)</entry> |
| <entry>Associative_Erase_</entry> |
| </row> |
| <row> |
| <entry>void associative_erase_( container , first, last)</entry> |
| <entry>Associative_Erase_</entry> |
| </row> |
| <row> |
| <entry>size_type associative_erase_( container , key)</entry> |
| <entry>Associative_Erase_</entry> |
| </row> |
| <row> |
| <entry>iterator associative_find_( container , key)</entry> |
| <entry>Associative_Find_</entry> |
| </row> |
| <row> |
| <entry>size_type associative_count_( container , key)</entry> |
| <entry>AssociativeCount_</entry> |
| </row> |
| <row> |
| <entry>iterator associative_lower_bound_( container , key)</entry> |
| <entry>Associative_Lower_Bound_</entry> |
| </row> |
| <row> |
| <entry>iterator associative_upper_bound_( container , key)</entry> |
| <entry>Associative_Upper_Bound_</entry> |
| </row> |
| <row> |
| <entry>pair<iterator, iterator> associative_equal_range_( |
| container , key)</entry> |
| <entry>Associative_Equal_Range_</entry> |
| </row> |
| </tbody> |
| </tgroup> |
| </table> |
| </para> |
| <para> |
| <table> |
| <title>STL pair</title> |
| <tgroup cols="2"> |
| <colspec colname="c2" colnum="1"/> |
| <colspec colname="c3" colnum="2"/> |
| <thead> |
| <row> |
| <entry>std::pair in container.hpp</entry> |
| <entry>Functor</entry> |
| </row> |
| </thead> |
| <tbody> |
| <row> |
| <entry>first_type first_(pair<T1, T2>)</entry> |
| <entry>First_</entry> |
| </row> |
| <row> |
| <entry>second_type second_(pair<T1, T2>)</entry> |
| <entry>Second_</entry> |
| </row> |
| </tbody> |
| </tgroup> |
| </table> |
| </para> |
| <para> |
| <table> |
| <title>STL string</title> |
| <tgroup cols="3"> |
| <colspec colname="newCol1" colnum="1"/> |
| <colspec colname="c2" colnum="2"/> |
| <colspec colname="c3" colnum="3"/> |
| <thead> |
| <row> |
| <entry>STL string method</entry> |
| <entry>std::string method in container.hpp</entry> |
| <entry>Functor</entry> |
| </row> |
| </thead> |
| <tbody> |
| <row> |
| <entry>substr (size_type pos, size_type size)</entry> |
| <entry>string substr_(container, pos, length)</entry> |
| <entry>Substr_</entry> |
| </row> |
| <row> |
| <entry>int compare(string)</entry> |
| <entry>int string_compare_(container, another_string)</entry> |
| <entry>StringCompare_</entry> |
| </row> |
| <row> |
| <entry>int compare(char*)</entry> |
| <entry>int string_compare_(container, another_string)</entry> |
| <entry>StringCompare_</entry> |
| </row> |
| <row> |
| <entry>int compare(size_type pos, size_type size, string)</entry> |
| <entry>int string_compare_(container, pos, size, |
| another_string)</entry> |
| <entry>StringCompare_</entry> |
| </row> |
| <row> |
| <entry>int compare (size_type pos, size_type size, string, size_type |
| length)</entry> |
| <entry>int string_compare_(container, pos, size, another_string, |
| length)</entry> |
| <entry>StringCompare_</entry> |
| </row> |
| <row> |
| <entry>string& append(const string&)</entry> |
| <entry>string& append_(container, another_string)</entry> |
| <entry>Append_</entry> |
| </row> |
| <row> |
| <entry>string& append (charT*)</entry> |
| <entry>string& append_(container, another_string)</entry> |
| <entry>Append_</entry> |
| </row> |
| <row> |
| <entry>string& append (string , size_type pos, size_type |
| size)</entry> |
| <entry>string& append_(container, other_string, pos, |
| size)</entry> |
| <entry>Append_</entry> |
| </row> |
| <row> |
| <entry>string& append (charT*, size_type size)</entry> |
| <entry>string& append_(container, another_string, |
| length)</entry> |
| <entry>Append_</entry> |
| </row> |
| <row> |
| <entry>string& append (size_type size, charT)</entry> |
| <entry>string& append_(container, size, char)</entry> |
| <entry>Append_</entry> |
| </row> |
| <row> |
| <entry>string& append (iterator begin, iterator end)</entry> |
| <entry>string& append_(container, begin, end)</entry> |
| <entry>Append_</entry> |
| </row> |
| <row> |
| <entry>string& insert (size_type pos, charT*)</entry> |
| <entry>string& string_insert_(container, pos, |
| other_string)</entry> |
| <entry>StringInsert_</entry> |
| </row> |
| <row> |
| <entry>string& insert(size_type pos, charT*,size_type n)</entry> |
| <entry>string& string_insert_(container, pos, other_string, |
| n)</entry> |
| <entry>StringInsert_</entry> |
| </row> |
| <row> |
| <entry>string& insert(size_type pos,size_type n, charT |
| c)</entry> |
| <entry>string& string_insert_(container, pos, n, c)</entry> |
| <entry>StringInsert_</entry> |
| </row> |
| <row> |
| <entry>string& insert (size_type pos, const string&)</entry> |
| <entry>string& string_insert_(container, pos, |
| other_string)</entry> |
| <entry>StringInsert_</entry> |
| </row> |
| <row> |
| <entry>string& insert (size_type pos, const string&, |
| size_type pos1, size_type n)</entry> |
| <entry>string& string_insert_(container, pos, other_string, |
| pos1, n)</entry> |
| <entry>StringInsert_</entry> |
| </row> |
| <row> |
| <entry>string& erase(size_type pos=0, size_type n=npos)</entry> |
| <entry>string& string_erase_(container, pos, n)</entry> |
| <entry>StringErase_</entry> |
| </row> |
| <row> |
| <entry>string& assign(const string&)</entry> |
| <entry>string& string_assign_(container, another_string)</entry> |
| <entry>StringAssign_</entry> |
| </row> |
| <row> |
| <entry>string& assign(const charT*)</entry> |
| <entry>string& string_assign_(container, another_string)</entry> |
| <entry>StringAssign_</entry> |
| </row> |
| <row> |
| <entry>string& assign(const string&, size_type pos, |
| size_type n)</entry> |
| <entry>string& string_assign_(container, another_string, pos, |
| n)</entry> |
| <entry>StringAssign_</entry> |
| </row> |
| <row> |
| <entry>string& assign(const charT*, size_type n)</entry> |
| <entry>string& string_assign_(container, another_string, |
| n)</entry> |
| <entry>StringAssign_</entry> |
| </row> |
| <row> |
| <entry>string& assign(size_type n, charT c)</entry> |
| <entry>string& string_assign_(container, n, c)</entry> |
| <entry>StringAssign_</entry> |
| </row> |
| <row> |
| <entry>string& assign(iterator first, iterator last)</entry> |
| <entry>string& string_assign_(container, first, last)</entry> |
| <entry>StringAssign_</entry> |
| </row> |
| <row> |
| <entry>string& replace(size_type pos, size_type n, const |
| string&)</entry> |
| <entry>string& string_replace_(container, pos, n, |
| another_string)</entry> |
| <entry>StringReplace_</entry> |
| </row> |
| <row> |
| <entry>string& replace(size_type pos, size_type n, const charT*, |
| size_type n1)</entry> |
| <entry>string& string_replace_(container, pos, n, |
| another_string, n1)</entry> |
| <entry>StringReplace_</entry> |
| </row> |
| <row> |
| <entry>string& replace(size_type pos, size_type n, const |
| charT*)</entry> |
| <entry>string& string_replace_(container, pos, n, |
| another_string)</entry> |
| <entry>StringReplace_</entry> |
| </row> |
| <row> |
| <entry>string& replace(size_type pos, size_type n, size_type n1, |
| charT c)</entry> |
| <entry>string& string_replace_(container, pos, n, n1, c)</entry> |
| <entry>StringReplace_</entry> |
| </row> |
| <row> |
| <entry>string& replace(iterator first, iterator last, const |
| string&)</entry> |
| <entry>string& string_replace_(container, first, last, |
| another_string)</entry> |
| <entry>StringReplace_</entry> |
| </row> |
| <row> |
| <entry>string& replace(iterator first, iterator last, const |
| charT*, size_type n)</entry> |
| <entry>string& string_replace_(container, first, last, |
| another_string, n)</entry> |
| <entry>StringReplace_</entry> |
| </row> |
| <row> |
| <entry>string& replace(iterator first, iterator last, const |
| charT*)</entry> |
| <entry>string& string_replace_(container, first, last, |
| another_string)</entry> |
| <entry>StringReplace_</entry> |
| </row> |
| <row> |
| <entry>string& replace(iterator first, iterator last, size_type |
| n, charT c)</entry> |
| <entry>string& string_replace_(container, first, last, n, |
| c)</entry> |
| <entry>StringReplace_</entry> |
| </row> |
| <row> |
| <entry>string& replace(iterator first, iterator last, iterator |
| f, iterator l)</entry> |
| <entry>string& string_replace_(container, first, last, f, |
| l)</entry> |
| <entry>StringReplace_</entry> |
| </row> |
| <row> |
| <entry>const charT* c_str()</entry> |
| <entry>const charT* c_str_(container)</entry> |
| <entry>CStr_</entry> |
| </row> |
| <row> |
| <entry>const charT* data()</entry> |
| <entry>const charT* string_data_(container)</entry> |
| <entry>StringData_</entry> |
| </row> |
| <row> |
| <entry>size_type copy(charT* buf, size_type n, size_type pos = |
| 0)</entry> |
| <entry>size_type string_copy_(container, buf, n, pos); size_type |
| string_copy_(container, buf, n) </entry> |
| <entry>StringCopy_</entry> |
| </row> |
| <row> |
| <entry>size_type find(charT* s, size_type pos, size_type n)</entry> |
| <entry>size_type string_find_(container, s, pos, n)</entry> |
| <entry>StringFind_</entry> |
| </row> |
| <row> |
| <entry>size_type find(charT* s, size_type pos=0)</entry> |
| <entry>size_type string_find_(container, s, pos); size_type |
| string_find_(container, s) </entry> |
| <entry>StringFind_</entry> |
| </row> |
| <row> |
| <entry>size_type find(const string& s, size_type pos=0)</entry> |
| <entry>size_type string_find_(container, s, pos) size_type |
| string_find_(container, s) </entry> |
| <entry>StringFind_</entry> |
| </row> |
| <row> |
| <entry>size_type find(charT c, size_type pos=0)</entry> |
| <entry>size_type string_find_(container, c, pos) size_type |
| string_find_(container, c) </entry> |
| <entry>StringFind_</entry> |
| </row> |
| <row> |
| <entry>size_type rfind(charT* s, size_type pos, size_type n)</entry> |
| <entry>size_type string_rfind_(container, s, pos, n)</entry> |
| <entry>StringRFind_</entry> |
| </row> |
| <row> |
| <entry>size_type rfind(charT* s, size_type pos=npos)</entry> |
| <entry>size_type string_rfind_(container, s, pos); size_type |
| string_rfind_(container, s) </entry> |
| <entry>StringRFind_</entry> |
| </row> |
| <row> |
| <entry>size_type rfind(const string& s, size_type |
| pos=npos)</entry> |
| <entry>size_type string_rfind_(container, s, pos); size_type |
| string_rfind_(container, s) </entry> |
| <entry>StringRFind_</entry> |
| </row> |
| <row> |
| <entry>size_type rfind(charT c, size_type pos=npos)</entry> |
| <entry>size_type string_rfind_(container, c, pos) size_type |
| string_rfind_(container, c) </entry> |
| <entry>StringRFind_</entry> |
| </row> |
| <row> |
| <entry>size_type find_first_of(charT* s, size_type pos, size_type |
| n)</entry> |
| <entry>size_type find_first_of_(container, s, pos, n)</entry> |
| <entry>StringFindFirstOf_</entry> |
| </row> |
| <row> |
| <entry>size_type find_first_of (charT* s, size_type pos=0)</entry> |
| <entry>size_type find_first_of_(container, s, pos); size_type |
| find_first_of_(container, s) </entry> |
| <entry>StringFindFirstOf_</entry> |
| </row> |
| <row> |
| <entry>size_type find_first_of (const string& s, size_type |
| pos=0)</entry> |
| <entry>size_type find_first_of_(container, s, pos); size_type |
| find_first_of_(container, s) </entry> |
| <entry>StringFindFirstOf_</entry> |
| </row> |
| <row> |
| <entry>size_type find_first_of (charT c, size_type pos=0)</entry> |
| <entry>size_type find_first_of_(container, c, pos) size_type |
| find_first_of_(container, c) </entry> |
| <entry>StringFindFirstOf_</entry> |
| </row> |
| <row> |
| <entry>size_type find_first_not_of(charT* s, size_type pos, |
| size_type n)</entry> |
| <entry>size_type find_first_not_of_(container, s, pos, n)</entry> |
| <entry>StringFindFirstNotOf_</entry> |
| </row> |
| <row> |
| <entry>size_type find_first_not_of (charT* s, size_type |
| pos=0)</entry> |
| <entry>size_type find_first_not_of_(container, s, pos); size_type |
| find_first_not_of_(container, s) </entry> |
| <entry>StringFindFirstNotOf_</entry> |
| </row> |
| <row> |
| <entry>size_type find_first_not_of (const string& s, size_type |
| pos=0)</entry> |
| <entry>size_type find_first_not_of_(container, s, pos); size_type |
| find_first_not_of_(container, s) </entry> |
| <entry>StringFindFirstNotOf_</entry> |
| </row> |
| <row> |
| <entry>size_type find_first_not_of (charT c, size_type |
| pos=0)</entry> |
| <entry>size_type find_first_not_of_(container, c, pos); size_type |
| find_first_not_of_(container, c) </entry> |
| <entry>StringFindFirstNotOf_</entry> |
| </row> |
| <row> |
| <entry>size_type find_last_of(charT* s, size_type pos, size_type |
| n)</entry> |
| <entry>size_type find_last_of_(container, s, pos, n)</entry> |
| <entry>StringFindLastOf_</entry> |
| </row> |
| <row> |
| <entry>size_type find_last_of (charT* s, size_type pos=npos)</entry> |
| <entry>size_type find_last_of_(container, s, pos); size_type |
| find_last_of_(container, s) </entry> |
| <entry>StringFindLastOf_</entry> |
| </row> |
| <row> |
| <entry>size_type find_last_of (const string& s, size_type |
| pos=npos)</entry> |
| <entry>size_type find_last_of_(container, s, pos); size_type |
| find_last_of_(container, s) </entry> |
| <entry>StringFindLastOf_</entry> |
| </row> |
| <row> |
| <entry>size_type find_last_of (charT c, size_type pos=npos)</entry> |
| <entry>size_type find_last_of_(container, c, pos); size_type |
| find_last_of_(container, c) </entry> |
| <entry>StringFindLastOf_</entry> |
| </row> |
| <row> |
| <entry>size_type find_last_not_of(charT* s, size_type pos, size_type |
| n)</entry> |
| <entry>size_type find_last_not_of_(container, s, pos, n)</entry> |
| <entry>StringFindLastNotOf_</entry> |
| </row> |
| <row> |
| <entry>size_type find_last_not_of (charT* s, size_type |
| pos=npos)</entry> |
| <entry>size_type find_last_not_of_(container, s, pos); size_type |
| find_last_of_(container, s) </entry> |
| <entry>StringFindLastNotOf_</entry> |
| </row> |
| <row> |
| <entry>size_type find_last_not_of (const string& s, size_type |
| pos=npos)</entry> |
| <entry>size_type find_last_not_of_(container, s, pos); size_type |
| find_last_not_of_(container, s) </entry> |
| <entry>StringFindLastNotOf_</entry> |
| </row> |
| <row> |
| <entry>size_type find_last_not_of (charT c, size_type |
| pos=npos)</entry> |
| <entry>size_type find_last_not_of_(container, c, pos); size_type |
| find_last_not_of_(container, c) </entry> |
| <entry>StringFindLastNotOf_</entry> |
| </row> |
| </tbody> |
| </tgroup> |
| </table> |
| </para> |
| <para><emphasis role="underline">Notes</emphasis>: <itemizedlist> |
| <listitem> |
| <para>ᵃ: algorithms requiring a predicate need to make them eUML compatible |
| by wrapping them inside a Predicate_ functor. For example, |
| std::less<int> => Predicate_<std::less<int> >()</para> |
| </listitem> |
| <listitem> |
| <para>ᵇ: If using the SGI STL implementation, these functors use the SGI |
| return value</para> |
| </listitem> |
| </itemizedlist> |
| </para> |
| </chapter> |
| <refentry> |
| <refnamediv> |
| <refname>Common headers</refname> |
| <refpurpose>The common types used by front- and back-ends</refpurpose> |
| </refnamediv> |
| <refsect1> |
| <title>msm/common.hpp</title> |
| <para>This header provides one type, wrap, which is an empty type whose only reason |
| to exist is to be cheap to construct, so that it can be used with mpl::for_each, |
| as shown in the Metaprogramming book, chapter 9.</para> |
| <classsynopsis> |
| <ooclass> |
| <classname>template <class Dummy> wrap{};</classname> |
| </ooclass> |
| </classsynopsis> |
| </refsect1> |
| <refsect1> |
| <title>msm/row_tags.hpp</title> |
| <para>This header contains the row type tags which front-ends can support partially |
| or totally. Please see the <command xlink:href="#internals-front-back-interface" |
| >Internals</command> section for a description of the different |
| types.</para> |
| </refsect1> |
| </refentry> |
| <refentry> |
| <refnamediv> |
| <refname>Back-end</refname> |
| <refpurpose>The back-end headers</refpurpose> |
| </refnamediv> |
| <refsect1> |
| <title>msm/back/state_machine.hpp</title> |
| <para> This header provides one type, state_machine, MSM's state machine engine |
| implementation.</para> |
| <classsynopsis> |
| <ooclass> |
| <classname>template <class Derived,class HistoryPolicy=NoHistory,class |
| CompilePolicy=favor_runtime_speed> state_machine</classname> |
| </ooclass> |
| </classsynopsis> |
| <refsect2> |
| <title> Template arguments </title> |
| <refsect3> |
| <title> Derived </title> |
| <para>The name of the front-end state machine definition. All three |
| front-ends are possible.</para> |
| </refsect3> |
| <refsect3> |
| <title> HistoryPolicy </title> |
| <para>The desired history. This can be: AlwaysHistory, NoHistory, |
| ShallowHistory. Default is NoHistory.</para> |
| </refsect3> |
| <refsect3> |
| <title> CompilePolicy </title> |
| <para>The trade-off performance / compile-time. There are two predefined |
| policies, favor_runtime_speed and favor_compile_time. Default is |
| favor_runtime_speed, best performance, longer compile-time. See <link |
| xlink:href="#backend-tradeof-rt-ct">the backend</link>.</para> |
| </refsect3> |
| </refsect2> |
| <refsect2> |
| <title> methods </title> |
| <refsect3> |
| <title>start</title> |
| <para> The start methods must be called before any call to process_event. It |
| activates the entry action of the initial state(s). This allows you to |
| choose when a state machine can start. See <link |
| xlink:href="#backend-start">backend</link>.</para> |
| <methodsynopsis> |
| <methodname>void start</methodname> |
| <methodparam> |
| <funcparams/> |
| </methodparam> |
| </methodsynopsis> |
| </refsect3> |
| <refsect3> |
| <title>process_event</title> |
| <para>The event processing method implements the double-dispatch. Each call |
| to this function with a new event type instantiates a new dispatch |
| algorithm and increases compile-time.</para> |
| <methodsynopsis> |
| <methodname>template <class Event> HandledEnum |
| process_event</methodname> |
| <methodparam> |
| <funcparams>Event const&</funcparams> |
| </methodparam> |
| </methodsynopsis> |
| </refsect3> |
| <refsect3> |
| <title>current_state</title> |
| <para>Returns the ids of currently active states. You will typically need it |
| only for debugging or logging purposes.</para> |
| <methodsynopsis> |
| <methodname>const int* current_state const</methodname> |
| <methodparam> |
| <funcparams/> |
| </methodparam> |
| </methodsynopsis> |
| </refsect3> |
| <refsect3> |
| <title>get_state_by_id</title> |
| <para>Returns the state whose id is given. As all states of a concrete state |
| machine share a common base state, the return value is a base state. If |
| the id corresponds to no state, a null pointer is returned.</para> |
| <methodsynopsis> |
| <methodname>const BaseState* get_state_by_id const</methodname> |
| <methodparam> |
| <funcparams>int id</funcparams> |
| </methodparam> |
| </methodsynopsis> |
| </refsect3> |
| <refsect3> |
| <title>is_contained</title> |
| <para>Helper returning true if the state machine is contained as a |
| submachine of another state machine.</para> |
| <methodsynopsis> |
| <methodname>bool is_contained const</methodname> |
| <methodparam> |
| <funcparams/> |
| </methodparam> |
| </methodsynopsis> |
| </refsect3> |
| <refsect3> |
| <title>get_state</title> |
| <para>Returns the required state of the state machine as a pointer. A |
| compile error will occur if the state is not to be found in the state |
| machine.</para> |
| <methodsynopsis> |
| <methodname>template <class State> State* get_state</methodname> |
| <methodparam> |
| <funcparams/> |
| </methodparam> |
| </methodsynopsis> |
| </refsect3> |
| <refsect3> |
| <title>get_state</title> |
| <para>Returns the required state of the state machine as a reference. A |
| compile error will occur if the state is not to be found in the state |
| machine.</para> |
| <methodsynopsis> |
| <methodname>template <class State> State& get_state</methodname> |
| <methodparam> |
| <funcparams/> |
| </methodparam> |
| </methodsynopsis> |
| </refsect3> |
| <refsect3> |
| <title>is_flag_active</title> |
| <para>Returns true if the given flag is currently active. A flag is active |
| if the active state of one region is tagged with this flag (using OR as |
| BinaryOp) or active states of <emphasis role="underline">all</emphasis> |
| regions (using AND as BinaryOp)</para> |
| <methodsynopsis> |
| <methodname>template <class Flag,class BinaryOp> bool |
| is_flag_active</methodname> |
| <methodparam> |
| <funcparams/> |
| </methodparam> |
| </methodsynopsis> |
| </refsect3> |
| <refsect3> |
| <title>is_flag_active</title> |
| <para>Returns true if the given flag is currently active. A flag is active |
| if the active state of one region is tagged with this flag.</para> |
| <methodsynopsis> |
| <methodname>template <class Flag> bool is_flag_active</methodname> |
| <methodparam> |
| <funcparams/> |
| </methodparam> |
| </methodsynopsis> |
| </refsect3> |
| <refsect3> |
| <title>visit_current_states</title> |
| <para>Visits all active states and their substates. A state is visited using |
| the <code>accept</code> method without argument. The base class of all |
| states must provide an <code>accept_sig</code> type.</para> |
| <methodsynopsis> |
| <methodname>void visit_current_states</methodname> |
| <methodparam> |
| <funcparams/> |
| </methodparam> |
| </methodsynopsis> |
| </refsect3> |
| <refsect3> |
| <title>visit_current_states</title> |
| <para>Visits all active states and their substates. A state is visited using |
| the <code>accept</code> method with arguments. The base class of all |
| states must provide an <code>accept_sig</code> type defining the |
| signature and thus the number and type of the parameters.</para> |
| <methodsynopsis> |
| <methodname>void visit_current_states</methodname> |
| <methodparam> |
| <funcparams>any-type param1, any-type param2,...</funcparams> |
| </methodparam> |
| </methodsynopsis> |
| </refsect3> |
| <refsect3> |
| <title>defer_event</title> |
| <para> Defers the provided event. This method can be called only if at least |
| one state defers an event or if the state machine provides the |
| <code>activate_deferred_events</code>(see <link |
| xlink:href="examples/Orthogonal-deferred2.cpp">example</link>) type |
| either directly or using the deferred_events configuration of eUML |
| (<code>configure_ << deferred_events</code>)</para> |
| <methodsynopsis> |
| <methodname>template <class Event> void defer_event</methodname> |
| <methodparam> |
| <funcparams>Event const&</funcparams> |
| </methodparam> |
| </methodsynopsis> |
| </refsect3> |
| </refsect2> |
| <refsect2> |
| <title>Types</title> |
| <refsect3> |
| <title>nr_regions </title> |
| <para>The number of orthogonal regions contained in the state machine</para> |
| </refsect3> |
| <refsect3> |
| <title>entry_pt</title> |
| <para>This nested type provides the necessary typedef for entry point |
| pseudostates. |
| <code>state_machine<...>::entry_pt<state_name></code> is a |
| transition's valid target inside the containing state machine's |
| transition table.</para> |
| <classsynopsis> |
| <ooclass> |
| <classname>entry_pt</classname> |
| </ooclass> |
| </classsynopsis> |
| </refsect3> |
| <refsect3> |
| <title>exit_pt</title> |
| <para>This nested type provides the necessary typedef for exit point |
| pseudostates. <code>state_machine<...>::exit_pt<state_name></code> |
| is a transition's valid source inside the containing state machine's |
| transition table.</para> |
| <classsynopsis> |
| <ooclass> |
| <classname>exit_pt</classname> |
| </ooclass> |
| </classsynopsis> |
| </refsect3> |
| <refsect3> |
| <title>direct</title> |
| <para>This nested type provides the necessary typedef for an explicit entry |
| inside a submachine. |
| <code>state_machine<...>::direct<state_name></code> is a |
| transition's valid target inside the containing state machine's |
| transition table.</para> |
| <classsynopsis> |
| <ooclass> |
| <classname>direct</classname> |
| </ooclass> |
| </classsynopsis> |
| </refsect3> |
| <refsect3> |
| <title>stt</title> |
| <para>Calling state_machine<frontend>::stt returns a mpl::vector |
| containing the transition table of the state machine. This type can then |
| be used with generate_state_set or generate_event_set.</para> |
| </refsect3> |
| </refsect2> |
| </refsect1> |
| <refsect1> |
| <title>args.hpp</title> |
| <para>This header provides one type, args. which provides the necessary types for a |
| visitor implementation.</para> |
| </refsect1> |
| <refsect1> |
| <title><command xml:id="history-interface"/>msm/back/history_policies.hpp</title> |
| <para>This header provides the out-of-the-box history policies supported by MSM. |
| There are 3 such policies.</para> |
| <refsect2> |
| <title>Every history policy must implement the following methods: </title> |
| <refsect3> |
| <title> set_initial_states </title> |
| <para> This method is called by msm::back::state_machine when constructed. |
| It gives the policy a chance to save the ids of all initial states |
| (passed as array).</para> |
| <funcsynopsis> |
| <funcprototype> |
| <funcdef>void set_initial_states</funcdef> |
| <paramdef> |
| <funcparams>int* const</funcparams> |
| </paramdef> |
| </funcprototype> |
| </funcsynopsis> |
| </refsect3> |
| <refsect3> |
| <title> history_exit </title> |
| <para>This method is called by msm::back::state_machine when the submachine |
| is exited. It gives the policy a chance to remember the ids of the last |
| active substates of this submachine (passed as array).</para> |
| <funcsynopsis> |
| <funcprototype> |
| <funcdef>void history_exit</funcdef> |
| <paramdef> |
| <funcparams>int* const</funcparams> |
| </paramdef> |
| </funcprototype> |
| </funcsynopsis> |
| </refsect3> |
| <refsect3> |
| <title> history_entry </title> |
| <para>This method is called by msm::back::state_machine when the submachine |
| is entered. It gives the policy a chance to set the active states |
| according to the policy's aim. The policy gets as parameter the event |
| which activated the submachine and returns an array of active states |
| ids.</para> |
| <funcsynopsis> |
| <funcprototype> |
| <funcdef>template <class Event> int* const history_exit</funcdef> |
| <paramdef> |
| <funcparams>Event const&</funcparams> |
| </paramdef> |
| </funcprototype> |
| </funcsynopsis> |
| </refsect3> |
| </refsect2> |
| <refsect2> |
| <title>Out-of-the-box policies: </title> |
| <refsect3> |
| <title>NoHistory</title> |
| <para>This policy is the default used by state_machine. No active state of a |
| submachine is remembered and at every new activation of the submachine, |
| the initial state(s) are activated. </para> |
| </refsect3> |
| <refsect3> |
| <title>AlwaysHistory</title> |
| <para>This policy is a non-UML-standard extension. The active state(s) of a |
| submachine is (are) always remembered at every new activation of the |
| submachine. </para> |
| </refsect3> |
| <refsect3> |
| <title>ShallowHistory</title> |
| <para>This policy activates the active state(s) of a submachine if the event |
| is found in the policy's event list. </para> |
| </refsect3> |
| </refsect2> |
| </refsect1> |
| <refsect1> |
| <title>msm/back/default_compile_policy.hpp</title> |
| <para>This header contains the definition of favor_runtime_speed. This policy has |
| two settings:<itemizedlist> |
| <listitem> |
| <para>Submachines dispatch faster because their transitions are added |
| into their containing machine's transition table instead of simply |
| forwarding events.</para> |
| </listitem> |
| <listitem> |
| <para>It solves transition conflicts at compile-time</para> |
| </listitem> |
| </itemizedlist></para> |
| </refsect1> |
| <refsect1> |
| <title>msm/back/favor_compile_time.hpp</title> |
| <para>This header contains the definition of favor_compile_time. This policy has two settings:<itemizedlist> |
| <listitem> |
| <para>Submachines dispatch is slower because all events, even those with |
| no dispatch chance, are forwarded to submachines. In exchange, no |
| row is added into the containing machine's transition table, which |
| reduces compile-time.</para> |
| </listitem> |
| <listitem> |
| <para>It solves transition conflicts at run-time.</para> |
| </listitem> |
| </itemizedlist></para> |
| </refsect1> |
| <refsect1> |
| <title>msm/back/metafunctions.hpp </title> |
| <para>This header contains metafunctions for use by the library. Three metafunctions |
| can be useful for the user:<itemizedlist> |
| <listitem> |
| <para><code>generate_state_set< stt ></code>: generates the list of |
| all states referenced by the transition table stt. If stt is a |
| recursive table (generated by |
| <code>recursive_get_transition_table</code>), the metafunction |
| finds recursively all states of the submachines. A non-recursive |
| table can be obtained with some_backend_fsm::stt.</para> |
| </listitem> |
| <listitem> |
| <para><code>generate_event_set< stt></code>: generates the list of |
| all events referenced by the transition table stt. If stt is a |
| recursive table (generated by |
| <code>recursive_get_transition_table</code>), the metafunction |
| finds recursively all events of the submachines. A non-recursive |
| table can be obtained with some_backend_fsm::stt.</para> |
| </listitem> |
| <listitem> |
| <para><code>recursive_get_transition_table<fsm></code>: recursively |
| extends the transition table of the state machine fsm with tables |
| from the submachines.</para> |
| </listitem> |
| </itemizedlist></para> |
| </refsect1> |
| <refsect1> |
| <title>msm/back/tools.hpp </title> |
| <para> This header contains a few metaprogramming tools to get some information out |
| of a state machine.</para> |
| <refsect2> |
| <title>fill_state_names </title> |
| <refsect3> |
| <title>attributes </title> |
| <para> fill_state_names has for attribute:<itemizedlist> |
| <listitem> |
| <para><code>char const** m_names</code>: an already allocated |
| array of const char* where the typeid-generated names of a |
| state machine states will be witten.</para> |
| </listitem> |
| </itemizedlist></para> |
| </refsect3> |
| <refsect3> |
| <title>constructor </title> |
| <constructorsynopsis> |
| <methodparam> |
| <funcparams>char const** names_to_fill</funcparams> |
| </methodparam> |
| </constructorsynopsis> |
| </refsect3> |
| <refsect3> |
| <title>usage</title> |
| <para> fill_state_names is made for use in a mpl::for_each iterating on a |
| state list and writing inside a pre-allocated array the state names. |
| Example:</para> |
| <programlisting>typedef some_fsm::stt Stt; |
| typedef msm::back::generate_state_set<Stt>::type all_states; //states |
| static char const* state_names[mpl::size<all_states>::value]; |
| // array to fill with names |
| // fill the names of the states defined in the state machine |
| mpl::for_each<all_states,boost::msm::wrap<mpl::placeholders::_1> > |
| (msm::back::fill_state_names<Stt>(state_names)); |
| // display all active states |
| for (unsigned int i=0;i<some_fsm::nr_regions::value;++i) |
| { |
| std::cout << " -> " |
| << state_names[my_fsm_instance.current_state()[i]] |
| << std::endl; |
| }</programlisting> |
| </refsect3> |
| </refsect2> |
| <refsect2> |
| <title>get_state_name </title> |
| <refsect3> |
| <title> attributes </title> |
| <para>get_state_name has for attributes:<itemizedlist> |
| <listitem> |
| <para>std::string& m_name: the return value of the |
| iteration</para> |
| </listitem> |
| <listitem> |
| <para>int m_state_id: the searched state's id</para> |
| </listitem> |
| </itemizedlist></para> |
| </refsect3> |
| <refsect3> |
| <title>constructor</title> |
| <para>The constructor takes as argument a reference to the string to fill |
| with the state name and the id which must be searched.</para> |
| <constructorsynopsis> |
| <methodparam> |
| <funcparams>string& name_to_fill,int state_id</funcparams> |
| </methodparam> |
| </constructorsynopsis> |
| </refsect3> |
| <refsect3> |
| <title> usage</title> |
| <para>This type is made for the same search as in the previous example, |
| using a mpl::for_each to iterate on states. After the iteration, the |
| state name reference has been set.</para> |
| </refsect3> |
| </refsect2> |
| <refsect2> |
| <title>display_type </title> |
| <refsect3> |
| <title> attributes </title> |
| <para>none</para> |
| </refsect3> |
| <refsect3> |
| <title> usage</title> |
| <para>Reusing the state list from the previous example, we can output all |
| state names:</para> |
| <para><code>mpl::for_each<all_states,boost::msm::wrap<mpl::placeholders::_1> |
| >(msm::back::display_type ());</code></para> |
| </refsect3> |
| </refsect2> |
| </refsect1> |
| </refentry> |
| <refentry> |
| <refnamediv> |
| <refname>Front-end</refname> |
| <refpurpose>The front-end headers</refpurpose> |
| </refnamediv> |
| <refsect1> |
| <title>msm/front/common_states.hpp</title> |
| <para>This header contains the predefined types to serve as base for states or state machines:<itemizedlist> |
| <listitem> |
| <para>default_base_state: non-polymorphic empty type.</para> |
| </listitem> |
| <listitem> |
| <para>polymorphic_state: type with a virtual destructor, which makes all |
| states polymorphic.</para> |
| </listitem> |
| </itemizedlist></para> |
| </refsect1> |
| <refsect1> |
| <title>msm/front/completion_event.hpp</title> |
| <para>This header contains one type, <code>none</code>. This type has several |
| meanings inside a transition table:<itemizedlist> |
| <listitem> |
| <para>as action or guard: that there is no action or guard</para> |
| </listitem> |
| <listitem> |
| <para>as target state: that the transition is an internal |
| transition</para> |
| </listitem> |
| <listitem> |
| <para>as event: the transition is an anonymous (completion) |
| transition</para> |
| </listitem> |
| </itemizedlist></para> |
| </refsect1> |
| <refsect1> |
| <title>msm/front/functor_row.hpp</title> |
| <para>This header implements the functor front-end's transitions and helpers.</para> |
| <refsect2> |
| <title>Row</title> |
| <refsect3> |
| <title>definition</title> |
| <classsynopsis> |
| <ooclass> |
| <classname>template <class Source,class Event,class Target,class |
| Action,class Guard> Row</classname> |
| </ooclass> |
| </classsynopsis> |
| </refsect3> |
| <refsect3> |
| <title>tags</title> |
| <para>row_type_tag is defined differently for every specialization:<itemizedlist> |
| <listitem> |
| <para>all 5 template parameters means a normal transition with |
| action and guard: <code>typedef row_tag |
| row_type_tag;</code></para> |
| </listitem> |
| <listitem> |
| <para>Row<Source,Event,Target,none,none> a normal transition |
| without action or guard: <code>typedef _row_tag |
| row_type_tag;</code></para> |
| </listitem> |
| <listitem> |
| <para>Row<Source,Event,Target,Action,none> a normal |
| transition without guard: <code>typedef a_row_tag |
| row_type_tag;</code></para> |
| </listitem> |
| <listitem> |
| <para>Row<Source,Event,Target,none,Guard> a normal transition |
| without action: <code>typedef g_row_tag |
| row_type_tag;</code></para> |
| </listitem> |
| <listitem> |
| <para>Row<Source,Event,none,Action,none> an internal |
| transition without guard: <code>typedef a_irow_tag |
| row_type_tag;</code></para> |
| </listitem> |
| <listitem> |
| <para>Row<Source,Event,none,none,Guard> an internal |
| transition without action: <code>typedef g_irow_tag |
| row_type_tag;</code></para> |
| </listitem> |
| <listitem> |
| <para>Row<Source,Event,none,none,Guard> an internal |
| transition with action and guard: <code>typedef irow_tag |
| row_type_tag;</code></para> |
| </listitem> |
| <listitem> |
| <para>Row<Source,Event,none,none,none> an internal transition |
| without action or guard: <code>typedef _irow_tag |
| row_type_tag;</code></para> |
| </listitem> |
| </itemizedlist></para> |
| </refsect3> |
| <refsect3> |
| <title>methods</title> |
| <para>Like any other front-end, Row implements the two necessary static |
| functions for action and guard call. Each function receives as parameter |
| the (deepest-level) state machine processsing the event, the event |
| itself, the source and target states and all the states contained in a |
| state machine.</para> |
| <funcsynopsis> |
| <funcprototype> |
| <funcdef>template <class Fsm,class SourceState,class TargetState, |
| class AllStates> static void action_call</funcdef> |
| <paramdef> |
| <funcparams>Fsm& fsm,Event const& |
| evt,SourceState&,TargetState,AllStates&</funcparams> |
| </paramdef> |
| </funcprototype> |
| </funcsynopsis> |
| <funcsynopsis> |
| <funcprototype> |
| <funcdef>template <class Fsm,class SourceState,class TargetState, |
| class AllStates> static bool guard_call</funcdef> |
| <paramdef> |
| <funcparams>Fsm& fsm,Event const& |
| evt,SourceState&,TargetState,AllStates&</funcparams> |
| </paramdef> |
| </funcprototype> |
| </funcsynopsis> |
| </refsect3> |
| </refsect2> |
| <refsect2> |
| <title>Internal</title> |
| <refsect3> |
| <title>definition</title> |
| <classsynopsis> |
| <ooclass> |
| <classname>template <class Event,class Action,class Guard> |
| Internal</classname> |
| </ooclass> |
| </classsynopsis> |
| </refsect3> |
| <refsect3> |
| <title>tags</title> |
| <para>row_type_tag is defined differently for every specialization:<itemizedlist> |
| <listitem> |
| <para>all 3 template parameters means an internal transition |
| with action and guard: <code>typedef sm_i_row_tag |
| row_type_tag;</code></para> |
| </listitem> |
| <listitem> |
| <para>Internal<Event,none,none> an internal transition |
| without action or guard: <code>typedef sm__i_row_tag |
| row_type_tag;</code></para> |
| </listitem> |
| <listitem> |
| <para>Internal<Event,Action,none> an internal transition |
| without guard: <code>typedef sm_a_i_row_tag |
| row_type_tag;</code></para> |
| </listitem> |
| <listitem> |
| <para>Internal<Event,none,Guard> an internal transition |
| without action: <code>typedef sm_g_i_row_tag |
| row_type_tag;</code></para> |
| </listitem> |
| </itemizedlist></para> |
| </refsect3> |
| <refsect3> |
| <title>methods</title> |
| <para>Like any other front-end, Internal implements the two necessary static |
| functions for action and guard call. Each function receives as parameter |
| the (deepest-level) state machine processsing the event, the event |
| itself, the source and target states and all the states contained in a |
| state machine.</para> |
| <funcsynopsis> |
| <funcprototype> |
| <funcdef>template <class Fsm,class SourceState,class TargetState, |
| class AllStates> static void action_call</funcdef> |
| <paramdef> |
| <funcparams>Fsm& fsm,Event const& |
| evt,SourceState&,TargetState,AllStates&</funcparams> |
| </paramdef> |
| </funcprototype> |
| </funcsynopsis> |
| <funcsynopsis> |
| <funcprototype> |
| <funcdef>template <class Fsm,class SourceState,class TargetState, |
| class AllStates> static bool guard_call</funcdef> |
| <paramdef> |
| <funcparams>Fsm& fsm,Event const& |
| evt,SourceState&,TargetState,AllStates&</funcparams> |
| </paramdef> |
| </funcprototype> |
| </funcsynopsis> |
| </refsect3> |
| </refsect2> |
| <refsect2> |
| <title>ActionSequence_</title> |
| <para>This functor calls every element of the template Sequence (which are also |
| callable functors) in turn. It is also the underlying implementation of the |
| eUML sequence grammar (action1,action2,...).</para> |
| <refsect3> |
| <title>definition</title> |
| <classsynopsis> |
| <ooclass> |
| <classname>template <class Sequence> ActionSequence_</classname> |
| </ooclass> |
| </classsynopsis> |
| </refsect3> |
| <refsect3> |
| <title>methods</title> |
| <para>This helper functor is made for use in a transition table and in a |
| state behavior and therefore implements an operator() with 3 and with 4 |
| arguments:</para> |
| <para> |
| <funcsynopsis> |
| <funcprototype> |
| <funcdef>template <class Evt,class Fsm,class |
| SourceState,class TargetState> operator()</funcdef> |
| <paramdef>Evt const& ,Fsm& ,SourceState& |
| ,TargetState& </paramdef> |
| </funcprototype> |
| </funcsynopsis> |
| </para> |
| <para> |
| <funcsynopsis> |
| <funcprototype> |
| <funcdef>template <class Evt,class Fsm,class State> |
| operator()</funcdef> |
| <paramdef>Evt const&, Fsm&, State&</paramdef> |
| </funcprototype> |
| </funcsynopsis> |
| </para> |
| </refsect3> |
| </refsect2> |
| <refsect2> |
| <title>Defer</title> |
| <refsect3> |
| <title>definition</title> |
| <classsynopsis> |
| <ooclass> |
| <classname>Defer</classname> |
| </ooclass> |
| </classsynopsis> |
| </refsect3> |
| <refsect3> |
| <title>methods</title> |
| <para>This helper functor is made for use in a transition table and |
| therefore implements an operator() with 4 arguments:</para> |
| <funcsynopsis> |
| <funcprototype> |
| <funcdef>template <class Evt,class Fsm,class SourceState,class |
| TargetState> operator()</funcdef> |
| <paramdef>Evt const&, Fsm& , SourceState&, |
| TargetState&</paramdef> |
| </funcprototype> |
| </funcsynopsis> |
| </refsect3> |
| </refsect2> |
| </refsect1> |
| <refsect1> |
| <title>msm/front/internal_row.hpp</title> |
| <para>This header implements the internal transition rows for use inside an |
| internal_transition_table. All these row types have no source or target state, |
| as the backend will recognize internal transitions from this |
| internal_transition_table.</para> |
| <refsect2> |
| <title>methods</title> |
| <para>Like any other front-end, the following transition row types implements |
| the two necessary static functions for action and guard call. Each function |
| receives as parameter the (deepest-level) state machine processsing the |
| event, the event itself, the source and target states and all the states |
| contained in a state machine.</para> |
| <funcsynopsis> |
| <funcprototype> |
| <funcdef>template <class Fsm,class SourceState,class TargetState, |
| class AllStates> static void action_call</funcdef> |
| <paramdef> |
| <funcparams>Fsm& fsm,Event const& |
| evt,SourceState&,TargetState,AllStates&</funcparams> |
| </paramdef> |
| </funcprototype> |
| </funcsynopsis> |
| <funcsynopsis> |
| <funcprototype> |
| <funcdef>template <class Fsm,class SourceState,class TargetState, |
| class AllStates> static bool guard_call</funcdef> |
| <paramdef> |
| <funcparams>Fsm& fsm,Event const& |
| evt,SourceState&,TargetState,AllStates&</funcparams> |
| </paramdef> |
| </funcprototype> |
| </funcsynopsis> |
| </refsect2> |
| <refsect2> |
| <title>a_internal</title> |
| <refsect3> |
| <title>definition</title> |
| <para>This is an internal transition with an action called during the |
| transition.</para> |
| <classsynopsis> |
| <ooclass> |
| <classname>template< class Event, class CalledForAction, void |
| (CalledForAction::*action)(Event const&)> |
| a_internal</classname> |
| </ooclass> |
| </classsynopsis> |
| </refsect3> |
| <refsect3> |
| <title>template parameters</title> |
| <para> |
| <itemizedlist> |
| <listitem> |
| <para>Event: the event triggering the internal |
| transition.</para> |
| </listitem> |
| <listitem> |
| <para>CalledForAction: the type on which the action method will |
| be called. It can be either a state of the containing state |
| machine or the state machine itself.</para> |
| </listitem> |
| <listitem> |
| <para>action: a pointer to the method which CalledForAction |
| provides.</para> |
| </listitem> |
| </itemizedlist> |
| </para> |
| </refsect3> |
| </refsect2> |
| <refsect2> |
| <title>g_internal</title> |
| <para>This is an internal transition with a guard called before the transition |
| and allowing the transition if returning true.</para> |
| <refsect3> |
| <title>definition</title> |
| <classsynopsis> |
| <ooclass> |
| <classname>template< class Event, class CalledForGuard, bool |
| (CalledForGuard::*guard)(Event const&)> |
| g_internal</classname> |
| </ooclass> |
| </classsynopsis> |
| </refsect3> |
| <refsect3> |
| <title>template parameters</title> |
| <para> |
| <itemizedlist> |
| <listitem> |
| <para>Event: the event triggering the internal |
| transition.</para> |
| </listitem> |
| <listitem> |
| <para>CalledForGuard: the type on which the guard method will be |
| called. It can be either a state of the containing state |
| machine or the state machine itself.</para> |
| </listitem> |
| <listitem> |
| <para>guard: a pointer to the method which CalledForGuard |
| provides.</para> |
| </listitem> |
| </itemizedlist> |
| </para> |
| </refsect3> |
| </refsect2> |
| <refsect2> |
| <title>internal</title> |
| <para>This is an internal transition with a guard called before the transition |
| and allowing the transition if returning true. It also calls an action |
| called during the transition.</para> |
| <refsect3> |
| <title>definition</title> |
| <classsynopsis> |
| <ooclass> |
| <classname>template< class Event, class CalledForAction, void |
| (CalledForAction::*action)(Event const&), class |
| CalledForGuard, bool (CalledForGuard::*guard)(Event const&)> |
| internal</classname> |
| </ooclass> |
| </classsynopsis> |
| </refsect3> |
| <refsect3> |
| <title>template parameters</title> |
| <para> |
| <itemizedlist> |
| <listitem> |
| <para>Event: the event triggering the internal transition</para> |
| </listitem> |
| <listitem> |
| <para>CalledForAction: the type on which the action method will |
| be called. It can be either a state of the containing state |
| machine or the state machine itself.</para> |
| </listitem> |
| <listitem> |
| <para>action: a pointer to the method which CalledForAction |
| provides.</para> |
| </listitem> |
| <listitem> |
| <para>CalledForGuard: the type on which the guard method will be |
| called. It can be either a state of the containing state |
| machine or the state machine itself.</para> |
| </listitem> |
| <listitem> |
| <para>guard: a pointer to the method which CalledForGuard |
| provides.</para> |
| </listitem> |
| </itemizedlist> |
| </para> |
| </refsect3> |
| </refsect2> |
| <refsect2> |
| <title>_internal</title> |
| <para>This is an internal transition without action or guard. This is equivalent |
| to an explicit "ignore event".</para> |
| <refsect3> |
| <title>definition</title> |
| <classsynopsis> |
| <ooclass> |
| <classname>template< class Event > _internal</classname> |
| </ooclass> |
| </classsynopsis> |
| </refsect3> |
| <refsect3> |
| <title>template parameters</title> |
| <para> |
| <itemizedlist> |
| <listitem> |
| <para>Event: the event triggering the internal |
| transition.</para> |
| </listitem> |
| </itemizedlist> |
| </para> |
| </refsect3> |
| </refsect2> |
| </refsect1> |
| <refsect1> |
| <title>msm/front/row2.hpp</title> |
| <para>This header contains the variants of row2, which are an extension of the |
| standard row transitions for use in the transition table. They offer the |
| possibility to define action and guard not only in the state machine, but in any |
| state of the state machine. They can also be used in internal transition tables |
| through their irow2 variants.</para> |
| <refsect2> |
| <title>methods</title> |
| <para>Like any other front-end, the following transition row types implements |
| the two necessary static functions for action and guard call. Each function |
| receives as parameter the (deepest-level) state machine processsing the |
| event, the event itself, the source and target states and all the states |
| contained in a state machine.</para> |
| <funcsynopsis> |
| <funcprototype> |
| <funcdef>template <class Fsm,class SourceState,class TargetState, |
| class AllStates> static void action_call</funcdef> |
| <paramdef> |
| <funcparams>Fsm& fsm,Event const& |
| evt,SourceState&,TargetState,AllStates&</funcparams> |
| </paramdef> |
| </funcprototype> |
| </funcsynopsis> |
| <funcsynopsis> |
| <funcprototype> |
| <funcdef>template <class Fsm,class SourceState,class TargetState, |
| class AllStates> static bool guard_call</funcdef> |
| <paramdef> |
| <funcparams>Fsm& fsm,Event const& |
| evt,SourceState&,TargetState,AllStates&</funcparams> |
| </paramdef> |
| </funcprototype> |
| </funcsynopsis> |
| </refsect2> |
| <refsect2> |
| <title>_row2</title> |
| <para>This is a transition without action or guard. The state machine only |
| changes active state.</para> |
| <refsect3> |
| <title>definition</title> |
| <classsynopsis> |
| <ooclass> |
| <classname>template< class Source, class Event, class Target > |
| _row2</classname> |
| </ooclass> |
| </classsynopsis> |
| </refsect3> |
| <refsect3> |
| <title>template parameters</title> |
| <para> |
| <itemizedlist> |
| <listitem> |
| <para>Event: the event triggering the transition.</para> |
| </listitem> |
| <listitem> |
| <para>Source: the source state of the transition.</para> |
| </listitem> |
| <listitem> |
| <para>Target: the target state of the transition.</para> |
| </listitem> |
| </itemizedlist> |
| </para> |
| </refsect3> |
| </refsect2> |
| <refsect2> |
| <title>a_row2</title> |
| <para>This is a transition with action and without guard.</para> |
| <refsect3> |
| <title>definition</title> |
| <classsynopsis> |
| <ooclass> |
| <classname>template< class Source, class Event, class Target, |
| </classname> |
| </ooclass> |
| </classsynopsis> |
| <classsynopsis> |
| <ooclass> |
| <classname>class CalledForAction, void |
| (CalledForAction::*action)(Event const&) > _row2</classname> |
| </ooclass> |
| </classsynopsis> |
| </refsect3> |
| <refsect3> |
| <title>template parameters</title> |
| <para> |
| <itemizedlist> |
| <listitem> |
| <para>Event: the event triggering the transition.</para> |
| </listitem> |
| <listitem> |
| <para>Source: the source state of the transition.</para> |
| </listitem> |
| <listitem> |
| <para>Target: the target state of the transition.</para> |
| </listitem> |
| <listitem> |
| <para>CalledForAction: the type on which the action method will |
| be called. It can be either a state of the containing state |
| machine or the state machine itself.</para> |
| </listitem> |
| <listitem> |
| <para>action: a pointer to the method which CalledForAction |
| provides.</para> |
| </listitem> |
| </itemizedlist> |
| </para> |
| </refsect3> |
| </refsect2> |
| <refsect2> |
| <title>g_row2</title> |
| <para>This is a transition with guard and without action.</para> |
| <refsect3> |
| <title>definition</title> |
| <classsynopsis> |
| <ooclass> |
| <classname>template< class Source, class Event, class Target, |
| </classname> |
| </ooclass> |
| </classsynopsis> |
| <classsynopsis> |
| <ooclass> |
| <classname>class CalledForGuard, bool (CalledForGuard::*guard)(Event |
| const&) > _row2</classname> |
| </ooclass> |
| </classsynopsis> |
| </refsect3> |
| <refsect3> |
| <title>template parameters</title> |
| <para> |
| <itemizedlist> |
| <listitem> |
| <para>Event: the event triggering the transition.</para> |
| </listitem> |
| <listitem> |
| <para>Source: the source state of the transition.</para> |
| </listitem> |
| <listitem> |
| <para>Target: the target state of the transition.</para> |
| </listitem> |
| <listitem> |
| <para>CalledForGuard: the type on which the guard method will be |
| called. It can be either a state of the containing state |
| machine or the state machine itself.</para> |
| </listitem> |
| <listitem> |
| <para>guard: a pointer to the method which CalledForGuard |
| provides.</para> |
| </listitem> |
| </itemizedlist> |
| </para> |
| </refsect3> |
| </refsect2> |
| <refsect2> |
| <title>row2</title> |
| <para>This is a transition with guard and action.</para> |
| <refsect3> |
| <title>definition</title> |
| <classsynopsis> |
| <ooclass> |
| <classname>template< class Source, class Event, class Target, |
| </classname> |
| </ooclass> |
| </classsynopsis> |
| <classsynopsis> |
| <ooclass> |
| <classname>class CalledForAction, void |
| (CalledForAction::*action)(Event const&), </classname> |
| </ooclass> |
| </classsynopsis> |
| <classsynopsis> |
| <ooclass> |
| <classname>class CalledForGuard, bool (CalledForGuard::*guard)(Event |
| const&) > _row2</classname> |
| </ooclass> |
| </classsynopsis> |
| </refsect3> |
| <refsect3> |
| <title>template parameters</title> |
| <para> |
| <itemizedlist> |
| <listitem> |
| <para>Event: the event triggering the transition.</para> |
| </listitem> |
| <listitem> |
| <para>Source: the source state of the transition.</para> |
| </listitem> |
| <listitem> |
| <para>Target: the target state of the transition.</para> |
| </listitem> |
| <listitem> |
| <para>CalledForAction: the type on which the action method will |
| be called. It can be either a state of the containing state |
| machine or the state machine itself.</para> |
| </listitem> |
| <listitem> |
| <para>action: a pointer to the method which CalledForAction |
| provides.</para> |
| </listitem> |
| <listitem> |
| <para>CalledForGuard: the type on which the guard method will be |
| called. It can be either a state of the containing state |
| machine or the state machine itself.</para> |
| </listitem> |
| <listitem> |
| <para>guard: a pointer to the method which CalledForGuard |
| provides.</para> |
| </listitem> |
| </itemizedlist> |
| </para> |
| </refsect3> |
| </refsect2> |
| <refsect2> |
| <title>a_irow2</title> |
| <para>This is an internal transition for use inside a transition table, with |
| action and without guard.</para> |
| <refsect3> |
| <title>definition</title> |
| <classsynopsis> |
| <ooclass> |
| <classname>template< class Source, class Event, </classname> |
| </ooclass> |
| </classsynopsis> |
| <classsynopsis> |
| <ooclass> |
| <classname>class CalledForAction, void |
| (CalledForAction::*action)(Event const&) > _row2</classname> |
| </ooclass> |
| </classsynopsis> |
| </refsect3> |
| <refsect3> |
| <title>template parameters</title> |
| <para> |
| <itemizedlist> |
| <listitem> |
| <para>Event: the event triggering the transition.</para> |
| </listitem> |
| <listitem> |
| <para>Source: the source state of the transition.</para> |
| </listitem> |
| <listitem> |
| <para>CalledForAction: the type on which the action method will |
| be called. It can be either a state of the containing state |
| machine or the state machine itself.</para> |
| </listitem> |
| <listitem> |
| <para>action: a pointer to the method which CalledForAction |
| provides.</para> |
| </listitem> |
| </itemizedlist> |
| </para> |
| </refsect3> |
| </refsect2> |
| <refsect2> |
| <title>g_irow2</title> |
| <para>This is an internal transition for use inside a transition table, with |
| guard and without action.</para> |
| <refsect3> |
| <title>definition</title> |
| <classsynopsis> |
| <ooclass> |
| <classname>template< class Source, class Event, </classname> |
| </ooclass> |
| </classsynopsis> |
| <classsynopsis> |
| <ooclass> |
| <classname>class CalledForGuard, bool (CalledForGuard::*guard)(Event |
| const&) > _row2</classname> |
| </ooclass> |
| </classsynopsis> |
| </refsect3> |
| <refsect3> |
| <title>template parameters</title> |
| <para> |
| <itemizedlist> |
| <listitem> |
| <para>Event: the event triggering the transition.</para> |
| </listitem> |
| <listitem> |
| <para>Source: the source state of the transition.</para> |
| </listitem> |
| <listitem> |
| <para>CalledForGuard: the type on which the guard method will be |
| called. It can be either a state of the containing state |
| machine or the state machine itself.</para> |
| </listitem> |
| <listitem> |
| <para>guard: a pointer to the method which CalledForGuard |
| provides.</para> |
| </listitem> |
| </itemizedlist> |
| </para> |
| </refsect3> |
| </refsect2> |
| <refsect2> |
| <title>irow2</title> |
| <para>This is an internal transition for use inside a transition table, with |
| guard and action.</para> |
| <refsect3> |
| <title>definition</title> |
| <classsynopsis> |
| <ooclass> |
| <classname>template< class Source, class Event, </classname> |
| </ooclass> |
| </classsynopsis> |
| <classsynopsis> |
| <ooclass> |
| <classname>class CalledForAction, void |
| (CalledForAction::*action)(Event const&), </classname> |
| </ooclass> |
| </classsynopsis> |
| <classsynopsis> |
| <ooclass> |
| <classname>class CalledForGuard, bool (CalledForGuard::*guard)(Event |
| const&) > _row2</classname> |
| </ooclass> |
| </classsynopsis> |
| </refsect3> |
| <refsect3> |
| <title>template parameters</title> |
| <para> |
| <itemizedlist> |
| <listitem> |
| <para>Event: the event triggering the transition.</para> |
| </listitem> |
| <listitem> |
| <para>Source: the source state of the transition.</para> |
| </listitem> |
| <listitem> |
| <para>CalledForAction: the type on which the action method will |
| be called. It can be either a state of the containing state |
| machine or the state machine itself.</para> |
| </listitem> |
| <listitem> |
| <para>action: a pointer to the method which CalledForAction |
| provides.</para> |
| </listitem> |
| <listitem> |
| <para>CalledForGuard: the type on which the guard method will be |
| called. It can be either a state of the containing state |
| machine or the state machine itself.</para> |
| </listitem> |
| <listitem> |
| <para>guard: a pointer to the method which CalledForGuard |
| provides.</para> |
| </listitem> |
| </itemizedlist> |
| </para> |
| </refsect3> |
| </refsect2> |
| </refsect1> |
| <refsect1> |
| <title>msm/front/state_machine_def.hpp</title> |
| <para>This header provides the implementation of the <command |
| xlink:href="#basic-front-end">basic front-end</command>. It contains one |
| type, <code>state_machine_def</code></para> |
| <refsect2> |
| <title>state_machine_def definition</title> |
| <para>This type is the basic class for a basic (or possibly any other) |
| front-end. It provides the standard row types (which includes internal |
| transitions) and a default implementation of the required methods and |
| typedefs.</para> |
| <classsynopsis> |
| <ooclass> |
| <classname>template <class Derived,class BaseState = |
| default_base_state> state_machine_def</classname> |
| </ooclass> |
| </classsynopsis> |
| <refsect3> |
| <title>typedefs</title> |
| <para> |
| <itemizedlist> |
| <listitem> |
| <para>flag_list: by default, no flag is set in the state |
| machine</para> |
| </listitem> |
| <listitem> |
| <para>deferred_events: by default, no event is deferred.</para> |
| </listitem> |
| <listitem> |
| <para>configuration: by default, no configuration customization |
| is done.</para> |
| </listitem> |
| </itemizedlist> |
| </para> |
| </refsect3> |
| <refsect3> |
| <title>row methods</title> |
| <para>Like any other front-end, the following transition row types |
| implements the two necessary static functions for action and guard call. |
| Each function receives as parameter the (deepest-level) state machine |
| processsing the event, the event itself, the source and target states |
| and all the states contained in a state machine (ignored).</para> |
| <funcsynopsis> |
| <funcprototype> |
| <funcdef>template <class Fsm,class SourceState,class TargetState, |
| class AllStates> static void action_call</funcdef> |
| <paramdef> |
| <funcparams>Fsm& fsm,Event const& |
| evt,SourceState&,TargetState,AllStates&</funcparams> |
| </paramdef> |
| </funcprototype> |
| </funcsynopsis> |
| <funcsynopsis> |
| <funcprototype> |
| <funcdef>template <class Fsm,class SourceState,class TargetState, |
| class AllStates> static bool guard_call</funcdef> |
| <paramdef> |
| <funcparams>Fsm& fsm,Event const& |
| evt,SourceState&,TargetState,AllStates&</funcparams> |
| </paramdef> |
| </funcprototype> |
| </funcsynopsis> |
| </refsect3> |
| <refsect3> |
| <title>a_row</title> |
| <para>This is a transition with action and without guard.</para> |
| <para><ooclass> |
| <classname>template< class Source, class Event, class Target, |
| void (Derived::*action)(Event const&) > a_row</classname> |
| </ooclass><itemizedlist> |
| <listitem> |
| <para>Event: the event triggering the transition.</para> |
| </listitem> |
| <listitem> |
| <para>Source: the source state of the transition.</para> |
| </listitem> |
| <listitem> |
| <para>Target: the target state of the transition.</para> |
| </listitem> |
| <listitem> |
| <para>action: a pointer to the method provided by the concrete |
| front-end (represented by <code>Derived</code>).</para> |
| </listitem> |
| </itemizedlist></para> |
| </refsect3> |
| <refsect3> |
| <title>g_row</title> |
| <para>This is a transition with guard and without action.</para> |
| <para><ooclass> |
| <classname>template< class Source, class Event, class Target, |
| bool (Derived::*guard)(Event const&) > g_row</classname> |
| </ooclass><itemizedlist> |
| <listitem> |
| <para>Event: the event triggering the transition.</para> |
| </listitem> |
| <listitem> |
| <para>Source: the source state of the transition.</para> |
| </listitem> |
| <listitem> |
| <para>Target: the target state of the transition.</para> |
| </listitem> |
| <listitem> |
| <para>guard: a pointer to the method provided by the concrete |
| front-end (represented by <code>Derived</code>).</para> |
| </listitem> |
| </itemizedlist></para> |
| </refsect3> |
| <refsect3> |
| <title>row</title> |
| <para>This is a transition with guard and action.</para> |
| <para><ooclass> |
| <classname>template< class Source, class Event, class Target, |
| void (Derived::*action)(Event const&), bool |
| (Derived::*guard)(Event const&) > row</classname> |
| </ooclass><itemizedlist> |
| <listitem> |
| <para>Event: the event triggering the transition.</para> |
| </listitem> |
| <listitem> |
| <para>Source: the source state of the transition.</para> |
| </listitem> |
| <listitem> |
| <para>Target: the target state of the transition.</para> |
| </listitem> |
| <listitem> |
| <para>action: a pointer to the method provided by the concrete |
| front-end (represented by <code>Derived</code>).</para> |
| </listitem> |
| <listitem> |
| <para>guard: a pointer to the method provided by the concrete |
| front-end (represented by <code>Derived</code>).</para> |
| </listitem> |
| </itemizedlist></para> |
| </refsect3> |
| <refsect3> |
| <title>_row</title> |
| <para>This is a transition without action or guard. The state machine only |
| changes active state.</para> |
| <para><ooclass> |
| <classname>template< class Source, class Event, class Target > |
| _row</classname> |
| </ooclass><itemizedlist> |
| <listitem> |
| <para>Event: the event triggering the transition.</para> |
| </listitem> |
| <listitem> |
| <para>Source: the source state of the transition.</para> |
| </listitem> |
| <listitem> |
| <para>Target: the target state of the transition.</para> |
| </listitem> |
| </itemizedlist></para> |
| </refsect3> |
| <refsect3> |
| <title>a_irow</title> |
| <para>This is an internal transition for use inside a transition table, with |
| action and without guard.</para> |
| <para><ooclass> |
| <classname>template< class Source, class Event, void |
| (Derived::*action)(Event const&) > a_irow</classname> |
| </ooclass><itemizedlist> |
| <listitem> |
| <para>Event: the event triggering the transition.</para> |
| </listitem> |
| <listitem> |
| <para>Source: the source state of the transition.</para> |
| </listitem> |
| <listitem> |
| <para>action: a pointer to the method provided by the concrete |
| front-end (represented by <code>Derived</code>).</para> |
| </listitem> |
| </itemizedlist></para> |
| </refsect3> |
| <refsect3> |
| <title>g_irow</title> |
| <para>This is an internal transition for use inside a transition table, with |
| guard and without action.</para> |
| <para><ooclass> |
| <classname>template< class Source, class Event, bool |
| (Derived::*guard)(Event const&) > g_irow</classname> |
| </ooclass><itemizedlist> |
| <listitem> |
| <para>Event: the event triggering the transition.</para> |
| </listitem> |
| <listitem> |
| <para>Source: the source state of the transition.</para> |
| </listitem> |
| <listitem> |
| <para>guard: a pointer to the method provided by the concrete |
| front-end (represented by <code>Derived</code>).</para> |
| </listitem> |
| </itemizedlist></para> |
| </refsect3> |
| <refsect3> |
| <title>irow</title> |
| <para>This is an internal transition for use inside a transition table, with |
| guard and action.</para> |
| <para><ooclass> |
| <classname>template< class Source, class Event, void |
| (Derived::*action)(Event const&), bool |
| (Derived::*guard)(Event const&) > irow</classname> |
| </ooclass><itemizedlist> |
| <listitem> |
| <para>Event: the event triggering the transition.</para> |
| </listitem> |
| <listitem> |
| <para>Source: the source state of the transition.</para> |
| </listitem> |
| <listitem> |
| <para>action: a pointer to the method provided by the concrete |
| front-end (represented by <code>Derived</code>).</para> |
| </listitem> |
| <listitem> |
| <para>guard: a pointer to the method provided by the concrete |
| front-end (represented by <code>Derived</code>).</para> |
| </listitem> |
| </itemizedlist></para> |
| </refsect3> |
| <refsect3> |
| <title>_irow</title> |
| <para>This is an internal transition without action or guard. As it does |
| nothing, it means "ignore event".</para> |
| <para><ooclass> |
| <classname>template< class Source, class Event > |
| _irow</classname> |
| </ooclass><itemizedlist> |
| <listitem> |
| <para>Event: the event triggering the transition.</para> |
| </listitem> |
| <listitem> |
| <para>Source: the source state of the transition.</para> |
| </listitem> |
| </itemizedlist></para> |
| </refsect3> |
| <refsect3> |
| <title>methods</title> |
| <para><code>state_machine_def</code> provides a default implementation in |
| case of an event which cannot be processed by a state machine (no |
| transition found). The implementation is using a |
| <code>BOOST_ASSERT</code> so that the error will only be noticed in |
| debug mode. Overwrite this method in your implementation to change the |
| behavior.</para> |
| <para> |
| <funcsynopsis> |
| <funcprototype> |
| <funcdef>template <class Fsm,class Event> static void |
| no_transition</funcdef> |
| <paramdef> |
| <funcparams>Event const& ,Fsm&, int |
| state</funcparams> |
| </paramdef> |
| </funcprototype> |
| </funcsynopsis> |
| </para> |
| <para><code>state_machine_def</code> provides a default implementation in |
| case an exception is thrown by a state (entry/exit) or transition |
| (action/guard) behavior. The implementation is using a |
| <code>BOOST_ASSERT</code> so that the error will only be noticed in |
| debug mode. Overwrite this method in your implementation to change the |
| behavior. This method will be called only if exception handling is not |
| deactivated (default) by defining |
| <code>has_no_message_queue</code>.</para> |
| <para> |
| <funcsynopsis> |
| <funcprototype> |
| <funcdef>template <class Fsm,class Event> static void |
| exception_caught</funcdef> |
| <paramdef> |
| <funcparams>Event const& ,Fsm&, |
| std::exception&</funcparams> |
| </paramdef> |
| </funcprototype> |
| </funcsynopsis> |
| </para> |
| </refsect3> |
| </refsect2> |
| </refsect1> |
| <refsect1> |
| <title>msm/front/states.hpp </title> |
| <para>This header provides the different states (except state machines) for the |
| basic front-end (or mixed with other front-ends).</para> |
| <refsect2> |
| <title>types</title> |
| <para>This header provides the following types:</para> |
| <refsect3> |
| <title>no_sm_ptr</title> |
| <para>deprecated: default policy for states. It means that states do not |
| need to save a pointer to their containing state machine.</para> |
| </refsect3> |
| <refsect3> |
| <title>sm_ptr</title> |
| <para>deprecated: state policy. It means that states need to save a pointer |
| to their containing state machine. When seeing this flag, the back-end |
| will call set_sm_ptr(fsm*) and give itself as argument.</para> |
| </refsect3> |
| <refsect3> |
| <title>state</title> |
| <para>Basic type for simple states. Inherit from this type to define a |
| simple state. The first argument is needed if you want your state (and |
| all others used in a concrete state machine) to inherit a basic type for |
| logging or providing a common behavior.</para> |
| <classsynopsis> |
| <ooclass> |
| <classname>template<class Base = default_base_state,class |
| SMPtrPolicy = no_sm_ptr> state</classname> |
| </ooclass> |
| </classsynopsis> |
| </refsect3> |
| <refsect3> |
| <title>terminate_state</title> |
| <para>Basic type for terminate states. Inherit from this type to define a |
| terminate state. The first argument is needed if you want your state |
| (and all others used in a concrete state machine) to inherit a basic |
| type for logging or providing a common behavior.</para> |
| <classsynopsis> |
| <ooclass> |
| <classname>template<class Base = default_base_state,class |
| SMPtrPolicy = no_sm_ptr> terminate_state</classname> |
| </ooclass> |
| </classsynopsis> |
| </refsect3> |
| <refsect3> |
| <title>interrupt_state</title> |
| <para>Basic type for interrupt states. Interrupt states prevent any further |
| event handling until EndInterruptEvent is sent. Inherit from this type |
| to define a terminate state. The first argument is the name of the event |
| ending the interrupt. The second argument is needed if you want your |
| state (and all others used in a concrete state machine) to inherit a |
| basic type for logging or providing a common behavior.</para> |
| <classsynopsis> |
| <ooclass> |
| <classname>template<class EndInterruptEvent,class Base = |
| default_base_state,</classname> |
| </ooclass> |
| </classsynopsis> |
| <classsynopsis> |
| <ooclass> |
| <classname>class SMPtrPolicy = no_sm_ptr> |
| interrupt_state</classname> |
| </ooclass> |
| </classsynopsis> |
| </refsect3> |
| <refsect3> |
| <title>explicit_entry</title> |
| <para>Inherit from this type <emphasis role="underline">in |
| addition</emphasis> to the desired state type to enable this state |
| for direct entering. The template parameter gives the region id of the |
| state (regions are numbered in the order of the |
| <code>initial_state</code> typedef).</para> |
| <classsynopsis> |
| <ooclass> |
| <classname>template <int ZoneIndex=-1> explicit_entry</classname> |
| </ooclass> |
| </classsynopsis> |
| </refsect3> |
| <refsect3> |
| <title>entry_pseudo_state</title> |
| <para>Basic type for entry pseudo states. Entry pseudo states are an |
| predefined entry into a submachine and connect two transitions. The |
| first argument is the id of the region entered by this state (regions |
| are numbered in the order of the <code>initial_state</code> typedef). |
| The second argument is needed if you want your state (and all others |
| used in a concrete state machine) to inherit a basic type for logging or |
| providing a common behavior.</para> |
| <classsynopsis> |
| <ooclass> |
| <classname>template<int RegionIndex=-1,class Base = |
| default_base_state,</classname> |
| </ooclass> |
| </classsynopsis> |
| <classsynopsis> |
| <ooclass> |
| <classname>class SMPtrPolicy = no_sm_ptr> |
| entry_pseudo_state</classname> |
| </ooclass> |
| </classsynopsis> |
| </refsect3> |
| <refsect3> |
| <title>exit_pseudo_state</title> |
| <para>Basic type for exit pseudo states. Exit pseudo states are an |
| predefined exit from a submachine and connect two transitions. The first |
| argument is the name of the event which will be "thrown" out of the exit |
| point. This event does not need to be the same as the one sent by the |
| inner region but must be convertible from it. The second argument is |
| needed if you want your state (and all others used in a concrete state |
| machine) to inherit a basic type for logging or providing a common |
| behavior.</para> |
| <classsynopsis> |
| <ooclass> |
| <classname>template<class Event,class Base = |
| default_base_state,</classname> |
| </ooclass> |
| </classsynopsis> |
| <classsynopsis> |
| <ooclass> |
| <classname>class SMPtrPolicy = no_sm_ptr> |
| exit_pseudo_state</classname> |
| </ooclass> |
| </classsynopsis> |
| </refsect3> |
| </refsect2> |
| </refsect1> |
| <refsect1> |
| <title>msm/front/euml/euml.hpp</title> |
| <para>This header includes all of eUML except the STL functors.</para> |
| </refsect1> |
| <refsect1> |
| <title>msm/front/euml/stl.hpp</title> |
| <para>This header includes all the functors for STL support in eUML. These <command |
| xlink:href="#eUML-STL-all">tables</command> show a full description.</para> |
| </refsect1> |
| <refsect1> |
| <title>msm/front/euml/algorithm.hpp</title> |
| <para>This header includes all the functors for STL algorithms support in eUML. |
| These <command xlink:href="#eUML-STL-all">tables</command> show a full |
| description.</para> |
| </refsect1> |
| <refsect1> |
| <title>msm/front/euml/iteration.hpp</title> |
| <para>This header includes iteration functors for STL support in eUML. This <command |
| xlink:href="#eUML-STL-iteration">tables</command> shows a full |
| description.</para> |
| </refsect1> |
| <refsect1> |
| <title>msm/front/euml/querying.hpp</title> |
| <para>This header includes querying functors for STL support in eUML. This <command |
| xlink:href="#eUML-STL-querying">tables</command> shows a full |
| description.</para> |
| </refsect1> |
| <refsect1> |
| <title>msm/front/euml/transformation.hpp</title> |
| <para>This header includes transformation functors for STL support in eUML. This |
| <command xlink:href="#eUML-STL-transformation">tables</command> shows a full |
| description.</para> |
| </refsect1> |
| <refsect1> |
| <title>msm/front/euml/container.hpp</title> |
| <para>This header includes container functors for STL support in eUML (functors |
| calling container methods). This <command xlink:href="#eUML-STL-container" |
| >tables</command> shows a full description. It also provides npos for |
| strings.</para> |
| <refsect2> |
| <title>Npos_<container type></title> |
| <para>Functor returning npos for transition or state behaviors. Like all |
| constants, only the functor form exists, so parenthesis are necessary. |
| Example:</para> |
| <para><code>string_find_(event_(m_song),Char_<'S'>(),Size_t_<0>()) != |
| Npos_<string>() // compare result of string::find with |
| npos</code></para> |
| </refsect2> |
| </refsect1> |
| <refsect1> |
| <title>msm/front/euml/stt_grammar.hpp</title> |
| <para>This header provides the transition table grammars. This includes internal |
| transition tables.</para> |
| <refsect2> |
| <title>functions</title> |
| <refsect3> |
| <title>build_stt</title> |
| <para>The function build_stt evaluates the grammar-conform expression as |
| parameter. It returns a transition table, which is a mpl::vector of |
| transitions (rows) or, if the expression is ill-formed (does not match |
| the grammar), the type <code>invalid_type</code>, which will lead to a |
| compile-time static assertion when this transition table is passed to a |
| state machine. </para> |
| <funcsynopsis> |
| <funcprototype> |
| <funcdef>template<class Expr> [mpl::vector<...> / |
| msm::front::euml::invalid_type] build_stt</funcdef> |
| <paramdef>Expr const& expr</paramdef> |
| </funcprototype> |
| </funcsynopsis> |
| </refsect3> |
| <refsect3> |
| <title>build_internal_stt</title> |
| <para>The function build_internal_stt evaluates the grammar-conform |
| expression as parameter. It returns a transition table, which is a |
| mpl::vector of transitions (rows) or, if the expression is ill-formed |
| (does not match the grammar), the type <code>invalid_type</code>, which |
| will lead to a compile-time static assertion when this transition table |
| is passed to a state machine. </para> |
| <funcsynopsis> |
| <funcprototype> |
| <funcdef>template<class Expr> [mpl::vector<...> / |
| msm::front::euml::invalid_type] build_internal_stt</funcdef> |
| <paramdef>Expr const& expr</paramdef> |
| </funcprototype> |
| </funcsynopsis> |
| </refsect3> |
| </refsect2> |
| <refsect2> |
| <title>grammars</title> |
| <refsect3> |
| <title><command xml:id="reference-stt-grammar">transition |
| table</command></title> |
| <para>The transition table accepts the following grammar:</para> |
| <programlisting>Stt := Row | (Stt ',' Stt) |
| Row := (Target '==' (SourcePlusEvent)) /* first syntax*/ |
| | ( (SourcePlusEvent) '==' Target ) /* second syntax*/ |
| | (SourcePlusEvent) /* internal transitions */ |
| SourcePlusEvent := (BuildSource '+' BuildEvent)/* standard transition*/ |
| | (BuildSource) /* anonymous transition */ |
| BuildSource := state_tag | (state_tag '/' Action) | (state_tag '[' Guard ']') |
| | (state_tag '[' Guard ']' '/' Action) |
| BuildEvent := event_tag | (event_tag '/' Action) | (event_tag '[' Guard ']') |
| | (event_tag '[' Guard ']' '/' Action)</programlisting> |
| <para>The grammars Action and Guard are defined in state_grammar.hpp and |
| guard_grammar.hpp respectively. state_tag and event_tag are inherited |
| from euml_state (or other state variants) and euml_event respectively. |
| For example, following declarations are possible:</para> |
| <programlisting>target == source + event [guard] / action, |
| source + event [guard] / action == target, |
| source + event [guard] / (action1,action2) == target, |
| target == source + event [guard] / (action1,action2), |
| target == source + event, |
| source + event == target, |
| target == source + event [guard], |
| source + event [guard] == target, |
| target == source + event / action, |
| source + event /action == target, |
| source / action == target, /*anonymous transition*/ |
| target == source / action, /*anonymous transition*/ |
| source + event /action, /* internal transition*/</programlisting> |
| </refsect3> |
| <refsect3> |
| <title>internal transition table</title> |
| <para>The internal transition table accepts the following grammar:</para> |
| <programlisting>IStt := BuildEvent | (IStt ',' IStt)</programlisting> |
| <para>BuildEvent being defined for both internal and standard transition |
| tables.</para> |
| </refsect3> |
| </refsect2> |
| </refsect1> |
| <refsect1> |
| <title>msm/front/euml/guard_grammar.hpp</title> |
| <para>This header contains the <code>Guard</code> grammar used in the previous |
| section. This grammar is long but pretty simple:</para> |
| <programlisting>Guard := action_tag | (Guard '&&' Guard) |
| | (Guard '||' Guard) | ... /* operators*/ |
| | (if_then_else_(Guard,Guard,Guard)) | (function (Action,...Action))</programlisting> |
| <para>Most C++ operators are supported (address-of is not). With |
| <code>function</code> is meant any eUML predefined function or any self-made |
| (using <code>MSM_EUML_METHOD</code> or <code>MSM_EUML_FUNCTION</code>). Action |
| is a grammar defined in state_grammar.hpp.</para> |
| </refsect1> |
| <refsect1> |
| <title>msm/front/euml/state_grammar.hpp</title> |
| <para>This header provides the grammar for actions and the different grammars and |
| functions to build states using eUML.</para> |
| <refsect2> |
| <title>action grammar</title> |
| <para>Like the guard grammar, this grammar supports relevant C++ operators and |
| eUML functions:</para> |
| <programlisting>Action := action_tag | (Action '+' Action) |
| | ('--' Action) | ... /* operators*/ |
| | if_then_else_(Guard,Action,Action) | if_then_(Action) |
| | while_(Guard,Action) |
| | do_while_(Guard,Action) | for_(Action,Guard,Action,Action) |
| | (function(Action,...Action)) |
| ActionSequence := Action | (Action ',' Action)</programlisting> |
| <para>Relevant operators are: ++ (post/pre), -- (post/pre), dereferencing, + |
| (unary/binary), - (unary/binary), *, /, %, &(bitwise), | (bitwise), |
| ^(bitwise), +=, -=, *=, /=, %=, <<=, >>=, <<, >>, =, [].</para> |
| </refsect2> |
| <refsect2> |
| <title>attributes</title> |
| <para>This grammar is used to add attributes to states (or state machines) or |
| events: It evaluates to a fusion::map. You can use two forms:<itemizedlist> |
| <listitem> |
| <para><code>attributes_ << no_attributes_</code></para> |
| </listitem> |
| <listitem> |
| <para><code>attributes_ << attribute_1 << ... << |
| attribute_n</code></para> |
| </listitem> |
| </itemizedlist></para> |
| <para>Attributes can be of any default-constructible type (fusion |
| requirement).</para> |
| </refsect2> |
| <refsect2> |
| <title>configure</title> |
| <para>This grammar also has two forms:<itemizedlist> |
| <listitem> |
| <para><code>configure_ << no_configure_</code></para> |
| </listitem> |
| <listitem> |
| <para><code>configure_ << type_1 << ... << |
| type_n</code></para> |
| </listitem> |
| </itemizedlist></para> |
| <para>This grammar is used to create inside one syntax:<itemizedlist> |
| <listitem> |
| <para>flags: <code>configure_ << some_flag</code> where |
| some_flag inherits from <code>euml_flag<some_flag></code> or |
| is defined using BOOST_MSM_EUML_FLAG.</para> |
| </listitem> |
| <listitem> |
| <para>deferred events: <code>configure_ << some_event</code> |
| where some_event inherits from |
| <code>euml_event<some_event></code> or is defined using |
| BOOST_MSM_EUML_EVENT or |
| BOOST_MSM_EUML_EVENT_WITH_ATTRIBUTES.</para> |
| </listitem> |
| <listitem> |
| <para>configuration (message queue, manual deferring, exception |
| handling): <code>configure_ << some_config</code> where |
| some_config inherits from |
| <code>euml_config<some_config></code>. At the moment, |
| three predefined objects exist (in msm//front/euml/common.hpp):<itemizedlist> |
| <listitem> |
| <para>no_exception: disable catching exceptions</para> |
| </listitem> |
| <listitem> |
| <para>no_msg_queue: disable message queue</para> |
| </listitem> |
| <listitem> |
| <para>deferred_events: manually enable handling of |
| deferred events</para> |
| </listitem> |
| </itemizedlist></para> |
| </listitem> |
| </itemizedlist></para> |
| </refsect2> |
| <refsect2> |
| <title>initial states</title> |
| <para>The grammar to define initial states for a state machine is: <code>init_ |
| << state_1 << ... << state_n</code> where |
| state_1...state_n inherit from euml_state or is defined using |
| BOOST_MSM_EUML_STATE, BOOST_MSM_EUML_INTERRUPT_STATE, |
| BOOST_MSM_EUML_TERMINATE_STATE, BOOST_MSM_EUML_EXPLICIT_ENTRY_STATE, |
| BOOST_MSM_EUML_ENTRY_STATE or BOOST_MSM_EUML_EXIT_STATE.</para> |
| </refsect2> |
| <refsect2> |
| <title>functions</title> |
| <refsect3> |
| <title>build_sm</title> |
| <para>This function has several overloads. The return type is not relevant |
| to you as only decltype (return type) is what one needs.</para> |
| <para>Defines a state machine without entry or exit:</para> |
| <funcsynopsis> |
| <funcprototype> |
| <funcdef>template <class StateNameTag,class Stt,class Init> |
| func_state_machine<...> build_sm</funcdef> |
| <paramdef>Stt ,Init</paramdef> |
| </funcprototype> |
| </funcsynopsis> |
| <para>Defines a state machine with entry behavior:</para> |
| <funcsynopsis> |
| <funcprototype> |
| <funcdef>template <class StateNameTag,class Stt,class Init,class |
| Expr1> func_state_machine<...> build_sm</funcdef> |
| <paramdef>Stt ,Init,Expr1 const&</paramdef> |
| </funcprototype> |
| </funcsynopsis> |
| <para>Defines a state machine with entry and exit behaviors:</para> |
| <funcsynopsis> |
| <funcprototype> |
| <funcdef>template <class StateNameTag,class Stt,class Init,class |
| Expr1, class Expr2> func_state_machine<...> |
| build_sm</funcdef> |
| <paramdef>Stt ,Init,Expr1 const&,Expr2 const&</paramdef> |
| </funcprototype> |
| </funcsynopsis> |
| <para>Defines a state machine with entry, exit behaviors and |
| attributes:</para> |
| <funcsynopsis> |
| <funcprototype> |
| <funcdef>template <class StateNameTag,class Stt,class Init,class |
| Expr1, class Expr2, class Attributes> func_state_machine<...> |
| build_sm</funcdef> |
| <paramdef>Stt ,Init,Expr1 const&, Expr2 const&, Attributes |
| const&</paramdef> |
| </funcprototype> |
| </funcsynopsis> |
| <para>Defines a state machine with entry, exit behaviors, attributes and |
| configuration (deferred events, flags):</para> |
| <funcsynopsis> |
| <funcprototype> |
| <funcdef>template <class StateNameTag,class Stt,class Init,class |
| Expr1, class Expr2, class Attributes, class Configure> |
| func_state_machine<...> build_sm</funcdef> |
| <paramdef>Stt ,Init,Expr1 const&, Expr2 const&, Attributes |
| const&, Configure const&</paramdef> |
| </funcprototype> |
| </funcsynopsis> |
| <para>Defines a state machine with entry, exit behaviors, attributes, |
| configuration (deferred events, flags) and a base state:</para> |
| <funcsynopsis> |
| <funcprototype> |
| <funcdef>template <class StateNameTag,class Stt,class Init,class |
| Expr1, class Expr2, class Attributes, class Configure, class |
| Base> func_state_machine<...> build_sm</funcdef> |
| <paramdef>Stt ,Init,Expr1 const&, Expr2 const&, Attributes |
| const&, Configure const&, Base</paramdef> |
| </funcprototype> |
| </funcsynopsis> |
| <para>Notice that this function requires the extra parameter class |
| StateNameTag to disambiguate state machines having the same parameters |
| but still being different.</para> |
| </refsect3> |
| <refsect3> |
| <title>build_state</title> |
| <para>This function has several overloads. The return type is not relevant |
| to you as only decltype (return type) is what one needs.</para> |
| <para>Defines a simple state without entry or exit:</para> |
| <funcsynopsis> |
| <funcprototype> |
| <funcdef>func_state<class StateNameTag,...> build_state</funcdef> |
| <paramdef/> |
| </funcprototype> |
| </funcsynopsis> |
| <para>Defines a simple state with entry behavior:</para> |
| <funcsynopsis> |
| <funcprototype> |
| <funcdef>template <class StateNameTag,class Expr1> |
| func_state<...> build_state</funcdef> |
| <paramdef>Expr1 const&</paramdef> |
| </funcprototype> |
| </funcsynopsis> |
| <para>Defines a simple state with entry and exit behaviors:</para> |
| <funcsynopsis> |
| <funcprototype> |
| <funcdef>template <class StateNameTag,class Expr1, class Expr2> |
| func_state<...> build_state</funcdef> |
| <paramdef>Expr1 const&,Expr2 const&</paramdef> |
| </funcprototype> |
| </funcsynopsis> |
| <para>Defines a simple state with entry, exit behaviors and |
| attributes:</para> |
| <funcsynopsis> |
| <funcprototype> |
| <funcdef>template <class StateNameTag,class Expr1, class Expr2, |
| class Attributes> func_state<...> build_state</funcdef> |
| <paramdef>Expr1 const&, Expr2 const&, Attributes |
| const&</paramdef> |
| </funcprototype> |
| </funcsynopsis> |
| <para>Defines a simple state with entry, exit behaviors, attributes and |
| configuration (deferred events, flags):</para> |
| <funcsynopsis> |
| <funcprototype> |
| <funcdef>template <class StateNameTag,class Expr1, class Expr2, |
| class Attributes, class Configure> func_state<...> |
| build_state</funcdef> |
| <paramdef>Expr1 const&, Expr2 const&, Attributes const&, |
| Configure const&</paramdef> |
| </funcprototype> |
| </funcsynopsis> |
| <para>Defines a simple state with entry, exit behaviors, attributes, |
| configuration (deferred events, flags) and a base state:</para> |
| <funcsynopsis> |
| <funcprototype> |
| <funcdef>template <class StateNameTag,class Expr1, class Expr2, |
| class Attributes, class Configure, class Base> |
| func_state<...> build_state</funcdef> |
| <paramdef>Expr1 const&, Expr2 const&, Attributes const&, |
| Configure const&, Base</paramdef> |
| </funcprototype> |
| </funcsynopsis> |
| <para>Notice that this function requires the extra parameter class |
| StateNameTag to disambiguate states having the same parameters but still |
| being different.</para> |
| </refsect3> |
| <refsect3> |
| <title>build_terminate_state</title> |
| <para>This function has the same overloads as build_state.</para> |
| </refsect3> |
| <refsect3> |
| <title>build_interrupt_state</title> |
| <para>This function has several overloads. The return type is not relevant |
| to you as only decltype (return type) is what one needs.</para> |
| <para>Defines an interrupt state without entry or exit:</para> |
| <funcsynopsis> |
| <funcprototype> |
| <funcdef>template <class StateNameTag,class EndInterruptEvent> |
| func_state<...> build_interrupt_state</funcdef> |
| <paramdef>EndInterruptEvent const&</paramdef> |
| </funcprototype> |
| </funcsynopsis> |
| <para>Defines an interrupt state with entry behavior:</para> |
| <funcsynopsis> |
| <funcprototype> |
| <funcdef>template <class StateNameTag,class |
| EndInterruptEvent,class Expr1> func_state<...> |
| build_interrupt_state</funcdef> |
| <paramdef>EndInterruptEvent const&,Expr1 const&</paramdef> |
| </funcprototype> |
| </funcsynopsis> |
| <para>Defines an interrupt state with entry and exit behaviors:</para> |
| <funcsynopsis> |
| <funcprototype> |
| <funcdef>template <class StateNameTag,class |
| EndInterruptEvent,class Expr1, class Expr2> func_state<...> |
| build_interrupt_state</funcdef> |
| <paramdef>EndInterruptEvent const&,Expr1 const&,Expr2 |
| const&</paramdef> |
| </funcprototype> |
| </funcsynopsis> |
| <para>Defines an interrupt state with entry, exit behaviors and |
| attributes:</para> |
| <funcsynopsis> |
| <funcprototype> |
| <funcdef>template <class StateNameTag,class |
| EndInterruptEvent,class Expr1, class Expr2, class Attributes> |
| func_state<...> build_interrupt_state</funcdef> |
| <paramdef>EndInterruptEvent const&,Expr1 const&, Expr2 |
| const&, Attributes const&</paramdef> |
| </funcprototype> |
| </funcsynopsis> |
| <para>Defines an interrupt state with entry, exit behaviors, attributes and |
| configuration (deferred events, flags):</para> |
| <funcsynopsis> |
| <funcprototype> |
| <funcdef>template <class StateNameTag,class |
| EndInterruptEvent,class Expr1, class Expr2, class Attributes, |
| class Configure> func_state<...> |
| build_interrupt_state</funcdef> |
| <paramdef>EndInterruptEvent const&,Expr1 const&, Expr2 |
| const&, Attributes const&, Configure |
| const&</paramdef> |
| </funcprototype> |
| </funcsynopsis> |
| <para>Defines an interrupt state with entry, exit behaviors, attributes, |
| configuration (deferred events, flags) and a base state:</para> |
| <funcsynopsis> |
| <funcprototype> |
| <funcdef>template <class StateNameTag,class |
| EndInterruptEvent,class Expr1, class Expr2, class Attributes, |
| class Configure, class Base> func_state<...> |
| build_interrupt_state</funcdef> |
| <paramdef>EndInterruptEvent const&,Expr1 const&, Expr2 |
| const&, Attributes const&, Configure const&, |
| Base</paramdef> |
| </funcprototype> |
| </funcsynopsis> |
| <para>Notice that this function requires the extra parameter class |
| StateNameTag to disambiguate states having the same parameters but still |
| being different.</para> |
| </refsect3> |
| <refsect3> |
| <title>build_entry_state</title> |
| <para>This function has several overloads. The return type is not relevant |
| to you as only decltype (return type) is what one needs.</para> |
| <para>Defines an entry pseudo state without entry or exit:</para> |
| <funcsynopsis> |
| <funcprototype> |
| <funcdef>template <class StateNameTag,int RegionIndex> |
| entry_func_state<...> build_entry_state</funcdef> |
| <paramdef/> |
| </funcprototype> |
| </funcsynopsis> |
| <para>Defines an entry pseudo state with entry behavior:</para> |
| <funcsynopsis> |
| <funcprototype> |
| <funcdef>template <class StateNameTag,int RegionIndex,class |
| Expr1> entry_func_state<...> build_entry_state</funcdef> |
| <paramdef>Expr1 const&</paramdef> |
| </funcprototype> |
| </funcsynopsis> |
| <para>Defines an entry pseudo state with entry and exit behaviors:</para> |
| <funcsynopsis> |
| <funcprototype> |
| <funcdef>template <class StateNameTag,int RegionIndex,class |
| Expr1, class Expr2> entry_func_state<...> |
| build_entry_state</funcdef> |
| <paramdef>Expr1 const&,Expr2 const&</paramdef> |
| </funcprototype> |
| </funcsynopsis> |
| <para>Defines an entry pseudo state with entry, exit behaviors and |
| attributes:</para> |
| <funcsynopsis> |
| <funcprototype> |
| <funcdef>template <class StateNameTag,int RegionIndex,class |
| Expr1, class Expr2, class Attributes> entry_func_state<...> |
| build_entry_state</funcdef> |
| <paramdef>Expr1 const&, Expr2 const&, Attributes |
| const&</paramdef> |
| </funcprototype> |
| </funcsynopsis> |
| <para>Defines an entry pseudo state with entry, exit behaviors, attributes |
| and configuration (deferred events, flags):</para> |
| <funcsynopsis> |
| <funcprototype> |
| <funcdef>template <class StateNameTag,int RegionIndex,class |
| Expr1, class Expr2, class Attributes, class Configure> |
| entry_func_state<...> build_entry_state</funcdef> |
| <paramdef>Expr1 const&, Expr2 const&, Attributes const&, |
| Configure const&</paramdef> |
| </funcprototype> |
| </funcsynopsis> |
| <para>Defines an entry pseudo state with entry, exit behaviors, attributes, |
| configuration (deferred events, flags) and a base state:</para> |
| <funcsynopsis> |
| <funcprototype> |
| <funcdef>template <class StateNameTag,int RegionIndex,class |
| Expr1, class Expr2, class Attributes, class Configure, class |
| Base> entry_func_state<...> build_entry_state</funcdef> |
| <paramdef>Expr1 const&, Expr2 const&, Attributes const&, |
| Configure const&, Base</paramdef> |
| </funcprototype> |
| </funcsynopsis> |
| <para>Notice that this function requires the extra parameter class |
| StateNameTag to disambiguate states having the same parameters but still |
| being different.</para> |
| </refsect3> |
| <refsect3> |
| <title>build_exit_state</title> |
| <para>This function has several overloads. The return type is not relevant |
| to you as only decltype (return type) is what one needs.</para> |
| <para>Defines an exit pseudo state without entry or exit:</para> |
| <funcsynopsis> |
| <funcprototype> |
| <funcdef>template <class StateNameTag,class Event> |
| exit_func_state<...> build_exit_state</funcdef> |
| <paramdef>Event const&</paramdef> |
| </funcprototype> |
| </funcsynopsis> |
| <para>Defines an exit pseudo state with entry behavior:</para> |
| <funcsynopsis> |
| <funcprototype> |
| <funcdef>template <class StateNameTag,class Event,class Expr1> |
| exit_func_state<...> build_exit_state</funcdef> |
| <paramdef>Event const&,Expr1 const&</paramdef> |
| </funcprototype> |
| </funcsynopsis> |
| <para>Defines an exit pseudo state with entry and exit behaviors:</para> |
| <funcsynopsis> |
| <funcprototype> |
| <funcdef>template <class StateNameTag,class Event,class Expr1, |
| class Expr2> exit_func_state<...> build_exit_state</funcdef> |
| <paramdef>Event const&,Expr1 const&,Expr2 |
| const&</paramdef> |
| </funcprototype> |
| </funcsynopsis> |
| <para>Defines an exit pseudo state with entry, exit behaviors and |
| attributes:</para> |
| <funcsynopsis> |
| <funcprototype> |
| <funcdef>template <class StateNameTag,class Event,class Expr1, |
| class Expr2, class Attributes> exit_func_state<...> |
| build_exit_state</funcdef> |
| <paramdef>Event const&,Expr1 const&, Expr2 const&, |
| Attributes const&</paramdef> |
| </funcprototype> |
| </funcsynopsis> |
| <para>Defines an exit pseudo state with entry, exit behaviors, attributes |
| and configuration (deferred events, flags):</para> |
| <funcsynopsis> |
| <funcprototype> |
| <funcdef>template <class StateNameTag,class Event,class Expr1, |
| class Expr2, class Attributes, class Configure> |
| exit_func_state<...> build_exit_state</funcdef> |
| <paramdef>Event const&,Expr1 const&, Expr2 const&, |
| Attributes const&, Configure const&</paramdef> |
| </funcprototype> |
| </funcsynopsis> |
| <para>Defines an exit pseudo state with entry, exit behaviors, attributes, |
| configuration (deferred events, flags) and a base state:</para> |
| <funcsynopsis> |
| <funcprototype> |
| <funcdef>template <class StateNameTag,class Event,class Expr1, |
| class Expr2, class Attributes, class Configure, class Base> |
| exit_func_state<...> build_exit_state</funcdef> |
| <paramdef>Event const&,Expr1 const&, Expr2 const&, |
| Attributes const&, Configure const&, Base</paramdef> |
| </funcprototype> |
| </funcsynopsis> |
| <para>Notice that this function requires the extra parameter class |
| StateNameTag to disambiguate states having the same parameters but still |
| being different.</para> |
| </refsect3> |
| <refsect3> |
| <title>build_explicit_entry_state</title> |
| <para>This function has the same overloads as build_entry_state and |
| explicit_entry_func_state as return type.</para> |
| </refsect3> |
| </refsect2> |
| </refsect1> |
| <refsect1> |
| <title>msm/front/euml/common.hpp</title> |
| <refsect2> |
| <title>types</title> |
| <refsect3> |
| <title>euml_event</title> |
| <para>The basic type for events with eUML.</para> |
| <classsynopsis> |
| <ooclass> |
| <classname>template <class EventName> euml_event;</classname> |
| </ooclass> |
| </classsynopsis> |
| <programlisting>struct play : euml_event<play>{};</programlisting> |
| </refsect3> |
| <refsect3> |
| <title>euml_state</title> |
| <para>The basic type for states with eUML. You will usually not use this |
| type directly as it is easier to use BOOST_MSM_EUML_STATE, |
| BOOST_MSM_EUML_INTERRUPT_STATE, BOOST_MSM_EUML_TERMINATE_STATE, |
| BOOST_MSM_EUML_EXPLICIT_ENTRY_STATE, BOOST_MSM_EUML_ENTRY_STATE or |
| BOOST_MSM_EUML_EXIT_STATE.</para> |
| <classsynopsis> |
| <ooclass> |
| <classname>template <class StateName> euml_state;</classname> |
| </ooclass> |
| </classsynopsis> |
| <para>You can however use this type directly if you want to provide your |
| state with extra functions or provide entry or exit behaviors without |
| functors, for example:</para> |
| <programlisting>struct Empty : public msm::front::state<> , public euml_state<Empty> |
| { |
| void foo() {...} |
| template <class Event,class Fsm> |
| void on_entry(Event const& evt,Fsm& fsm){...} |
| };</programlisting> |
| </refsect3> |
| <refsect3> |
| <title>euml_flag</title> |
| <para>The basic type for flags with eUML.</para> |
| <classsynopsis> |
| <ooclass> |
| <classname>template <class FlagName> euml_flag;</classname> |
| </ooclass> |
| </classsynopsis> |
| <programlisting>struct PlayingPaused: euml_flag<PlayingPaused>{};</programlisting> |
| </refsect3> |
| <refsect3> |
| <title>euml_action</title> |
| <para>The basic type for state or transition behaviors and guards with |
| eUML.</para> |
| <classsynopsis> |
| <ooclass> |
| <classname>template <class AcionName> euml_action;</classname> |
| </ooclass> |
| </classsynopsis> |
| <programlisting>struct close_drawer : euml_action<close_drawer> |
| { |
| template <class Fsm,class Evt,class SourceState,class TargetState> |
| void operator()(Evt const& , Fsm&, SourceState& ,TargetState& ) {...} |
| };</programlisting> |
| <para>Or, as state entry or exit behavior:</para> |
| <programlisting>struct Playing_Entry : euml_action<Playing_Entry> |
| { |
| template <class Event,class Fsm,class State> |
| void operator()(Event const&,Fsm& fsm,State& ){...} |
| };</programlisting> |
| </refsect3> |
| <refsect3> |
| <title>euml_config</title> |
| <para>The basic type for configuration possibilities with eUML.</para> |
| <classsynopsis> |
| <ooclass> |
| <classname>template <class ConfigName> euml_config;</classname> |
| </ooclass> |
| </classsynopsis> |
| <para>You normally do not use this type directly but instead the instances |
| of predefined configuration:<itemizedlist> |
| <listitem> |
| <para>no_exception: disable catching exceptions</para> |
| </listitem> |
| <listitem> |
| <para>no_msg_queue: disable message queue. The message queue |
| allows you to send an event for procesing while in an event |
| processing.</para> |
| </listitem> |
| <listitem> |
| <para>deferred_events: manually enable handling of deferred |
| events</para> |
| </listitem> |
| </itemizedlist></para> |
| </refsect3> |
| <refsect3> |
| <title>invalid_type</title> |
| <para>Type returned by grammar parsers if the grammar is invalid. Seeing |
| this type will result in a static assertion.</para> |
| </refsect3> |
| <refsect3> |
| <title>no_action</title> |
| <para>Placeholder type for use in entry/exit or transition behaviors, which |
| does absolutely nothing.</para> |
| </refsect3> |
| <refsect3> |
| <title>source_</title> |
| <para>Generic object or function for the source state of a given transition:<itemizedlist> |
| <listitem> |
| <para>as object: returns by reference the source state of a |
| transition, usually to be used by another function (usually |
| one created by MSM_EUML_METHOD or MSM_EUML_FUNCTION).</para> |
| <para>Example: |
| <programlisting>some_user_function_(source_)</programlisting></para> |
| </listitem> |
| <listitem> |
| <para>as function: returns by reference the attribute passed as |
| parameter.</para> |
| <para>Example: |
| <programlisting>source_(m_counter)++</programlisting></para> |
| </listitem> |
| </itemizedlist></para> |
| </refsect3> |
| <refsect3> |
| <title>target_</title> |
| <para>Generic object or function for the target state of a given transition:<itemizedlist> |
| <listitem> |
| <para>as object: returns by reference the target state of a |
| transition, usually to be used by another function (usually |
| one created by MSM_EUML_METHOD or MSM_EUML_FUNCTION).</para> |
| <para>Example: |
| <programlisting>some_user_function_(target_)</programlisting></para> |
| </listitem> |
| <listitem> |
| <para>as function: returns by reference the attribute passed as |
| parameter.</para> |
| <para>Example: |
| <programlisting>target_(m_counter)++</programlisting></para> |
| </listitem> |
| </itemizedlist></para> |
| </refsect3> |
| <refsect3> |
| <title>state_</title> |
| <para>Generic object or function for the state of a given entry / exit |
| behavior. state_ means source_ while in the context of an exit behavior |
| and target_ in the context of an entry behavior:<itemizedlist> |
| <listitem> |
| <para>as object: returns by reference the current state, usually |
| to be used by another function (usually one created by |
| MSM_EUML_METHOD or MSM_EUML_FUNCTION).</para> |
| <para>Example: |
| <programlisting>some_user_function_(state_) // calls some_user_function on the current state</programlisting></para> |
| </listitem> |
| <listitem> |
| <para>as function: returns by reference the attribute passed as |
| parameter.</para> |
| <para>Example: |
| <programlisting>state_(m_counter)++</programlisting></para> |
| </listitem> |
| </itemizedlist></para> |
| </refsect3> |
| <refsect3> |
| <title>event_</title> |
| <para>Generic object or function for the event triggering a given transition |
| (valid in a transition behavior, as well as in state entry/exit behaviors):<itemizedlist> |
| <listitem> |
| <para>as object: returns by reference the event of a transition, |
| usually to be used by another function (usually one created |
| by MSM_EUML_METHOD or MSM_EUML_FUNCTION).</para> |
| <para>Example: |
| <programlisting>some_user_function_(event_)</programlisting></para> |
| </listitem> |
| <listitem> |
| <para>as function: returns by reference the attribute passed as |
| parameter.</para> |
| <para>Example: |
| <programlisting>event_(m_counter)++</programlisting></para> |
| </listitem> |
| </itemizedlist></para> |
| </refsect3> |
| <refsect3> |
| <title>fsm_</title> |
| <para>Generic object or function for the state machine containing a given transition:<itemizedlist> |
| <listitem> |
| <para>as object: returns by reference the event of a transition, |
| usually to be used by another function (usually one created |
| by MSM_EUML_METHOD or MSM_EUML_FUNCTION).</para> |
| <para>Example: |
| <programlisting>some_user_function_(fsm_)</programlisting></para> |
| </listitem> |
| <listitem> |
| <para>as function: returns by reference the attribute passed as |
| parameter.</para> |
| <para>Example: |
| <programlisting>fsm_(m_counter)++</programlisting></para> |
| </listitem> |
| </itemizedlist></para> |
| </refsect3> |
| <refsect3> |
| <title>substate_</title> |
| <para>Generic object or function returning a state of a given state machine:<itemizedlist> |
| <listitem> |
| <para>with 1 parameter: returns by reference the state passed as |
| parameter, usually to be used by another function (usually |
| one created by MSM_EUML_METHOD or MSM_EUML_FUNCTION).</para> |
| <para>Example: |
| <programlisting>some_user_function_(substate_(my_state))</programlisting></para> |
| </listitem> |
| <listitem> |
| <para>with 2 parameters: returns by reference the state passed |
| as first parameter from the state machine passed as second |
| parameter, usually to be used by another function (usually |
| one created by MSM_EUML_METHOD or MSM_EUML_FUNCTION). This |
| makes sense when used in combination with attribute_.</para> |
| <para>Example (equivalent to the previous example): |
| <programlisting>some_user_function_(substate_(my_state,fsm_))</programlisting></para> |
| </listitem> |
| </itemizedlist></para> |
| </refsect3> |
| <refsect3> |
| <title>attribute_</title> |
| <para>Generic object or function returning the attribute passed (by name) as |
| second parameter of the thing passed as first (a state, event or state |
| machine). Example: </para> |
| <para> |
| <programlisting>attribute_(substate_(my_state),cd_name_attribute)++</programlisting> |
| </para> |
| </refsect3> |
| <refsect3> |
| <title>True_</title> |
| <para>Functor returning true for transition or state behaviors. Like all |
| constants, only the functor form exists, so parenthesis are necessary. |
| Example:</para> |
| <para> |
| <programlisting>if_then_(True_(),/* some action always called*/)</programlisting> |
| </para> |
| </refsect3> |
| <refsect3> |
| <title>False_</title> |
| <para>Functor returning false for transition or state behaviors. Like all |
| constants, only the functor form exists, so parenthesis are necessary. |
| Example:</para> |
| <para> |
| <programlisting>if_then_(False_(),/* some action never called */)</programlisting> |
| </para> |
| </refsect3> |
| <refsect3> |
| <title>Int_<int value></title> |
| <para>Functor returning an integer value for transition or state behaviors. |
| Like all constants, only the functor form exists, so parenthesis are |
| necessary. Example:</para> |
| <para> |
| <programlisting>target_(m_ringing_cpt) = Int_<RINGING_TIME>() // RINGING_TIME is a constant</programlisting> |
| </para> |
| </refsect3> |
| <refsect3> |
| <title>Char_<char value></title> |
| <para>Functor returning a char value for transition or state behaviors. Like |
| all constants, only the functor form exists, so parenthesis are |
| necessary. Example:</para> |
| <para> |
| <programlisting>// look for 'S' in event.m_song |
| [string_find_(event_(m_song),Char_<'S'>(),Size_t_<0>()) != Npos_<string>()]</programlisting> |
| </para> |
| </refsect3> |
| <refsect3> |
| <title>Size_t_<size_t value></title> |
| <para>Functor returning a size_t value for transition or state behaviors. |
| Like all constants, only the functor form exists, so parenthesis are |
| necessary. Example:</para> |
| <para> |
| <programlisting>substr_(event_(m_song),Size_t_<1>()) // returns a substring of event.m_song</programlisting> |
| </para> |
| </refsect3> |
| <refsect3> |
| <title>String_ < mpl::string ></title> |
| <para>Functor returning a string for transition or state behaviors. Like all |
| constants, only the functor form exists, so parenthesis are necessary. |
| Requires boost >= 1.40 for mpl::string.</para> |
| <para>Example:</para> |
| <para> |
| <programlisting>// adds "Let it be" to fsm.m_src_container |
| push_back_(fsm_(m_src_container), String_<mpl::string<'Let','it ','be'> >())</programlisting> |
| </para> |
| </refsect3> |
| <refsect3> |
| <title>Predicate_ < some_stl_compatible_functor ></title> |
| <para>This functor eUML-enables a STL functor (for use in an algorithm). |
| This is necessary because all what is in the transition table must be a |
| eUML terminal.</para> |
| <para>Example:</para> |
| <programlisting>//equivalent to: |
| //std::accumulate(fsm.m_vec.begin(),fsm.m_vec.end(),1,std::plus<int>())== 1 |
| accumulate_(begin_(fsm_(m_vec)),end_(fsm_(m_vec)),Int_<1>(), |
| Predicate_<std::plus<int> >()) == Int_<1>())</programlisting> |
| </refsect3> |
| <refsect3> |
| <title>process_</title> |
| <para>This function sends an event to up to 4 state machines by calling |
| <code>process_event</code> on them:<itemizedlist> |
| <listitem> |
| <para><code>process_(some_event)</code> : processes an event in |
| the current (containing) state machine.</para> |
| </listitem> |
| <listitem> |
| <para><code>process_(some_event [,fsm1...fsm4] )</code> : |
| processes the same event in the 1-4 state machines passed as |
| argument.</para> |
| </listitem> |
| </itemizedlist></para> |
| </refsect3> |
| <refsect3> |
| <title>process2_</title> |
| <para>This function sends an event to up to 3 state machines by calling |
| <code>process_event</code> on them and copy-constructing the event |
| from the data passed as second parameter:<itemizedlist> |
| <listitem> |
| <para><code>process2_(some_event, some_data)</code> : processes |
| an event in the current (containing) state machine.</para> |
| </listitem> |
| <listitem> |
| <para><code>process2_(some_event, some_data [,fsm1...fsm3] |
| )</code> : processes the same event in the 1-3 state |
| machines passed as argument.</para> |
| </listitem> |
| </itemizedlist></para> |
| <para>Example: </para> |
| <para> |
| <programlisting>// processes NotFound on current state machine, |
| // copy-constructed with event.m_song |
| process2_(NotFound,event_(m_song))</programlisting> |
| </para> |
| <para>With the following definitions:</para> |
| <programlisting>BOOST_MSM_EUML_DECLARE_ATTRIBUTE(std::string,m_song)//declaration of m_song |
| NotFound (const string& data) // copy-constructor of NotFound</programlisting> |
| </refsect3> |
| <refsect3> |
| <title>is_flag_</title> |
| <para>This function tells if a flag is active by calling |
| <code>is_flag_active</code> on the current state machine or one |
| passed as parameter:<itemizedlist> |
| <listitem> |
| <para><code>is_flag_(some_flag)</code> : calls |
| <code>is_flag_active</code> on the current (containing) |
| state machine.</para> |
| </listitem> |
| <listitem> |
| <para><code>is_flag_(some_flag, some_fsm)</code> :calls |
| <code>is_flag_active</code> on the state machine.passed |
| as argument.</para> |
| </listitem> |
| </itemizedlist></para> |
| </refsect3> |
| <refsect3> |
| <title>defer_</title> |
| <para>This object defers the current event by calling |
| <code>defer_event</code> on the current state machine. |
| Example:</para> |
| <programlisting>Empty() + play() / defer_</programlisting> |
| </refsect3> |
| <refsect3> |
| <title>explicit_(submachine-name,state-name)</title> |
| <para>Used as transition's target, causes an explicit entry into the given |
| state from the given submachine. Several explicit_ as targets, separated |
| by commas, means a fork. The state must have been declared as such using |
| BOOST_MSM_EUML_EXPLICIT_ENTRY_STATE.</para> |
| </refsect3> |
| <refsect3> |
| <title>entry_pt_(submachine-name,state-name)</title> |
| <para>Used as transition's target from a containing state machine, causes |
| submachine-name to be entered using the given entry pseudo-state. This |
| state must have been declared as pseudo entry using |
| BOOST_MSM_EUML_ENTRY_STATE.</para> |
| </refsect3> |
| <refsect3> |
| <title>exit_pt_(submachine-name,state-name)</title> |
| <para>Used as transition's source from a containing state machine, causes |
| submachine-name to be left using the given exit pseudo-state. This state |
| must have been declared as pseudo exit using |
| BOOST_MSM_EUML_EXIT_STATE.</para> |
| </refsect3> |
| <refsect3> |
| <title>MSM_EUML_FUNCTION</title> |
| <para>This macro creates a eUML function and a functor for use with the |
| functor front-end, based on a free function:<itemizedlist> |
| <listitem> |
| <para>first parameter: the name of the functor</para> |
| </listitem> |
| <listitem> |
| <para>second parameter: the underlying function</para> |
| </listitem> |
| <listitem> |
| <para>third parameter: the eUML function name</para> |
| </listitem> |
| <listitem> |
| <para>fourth parameter: the return type if used in a transition |
| behavior</para> |
| </listitem> |
| <listitem> |
| <para>fifth parameter: the return type if used in a state |
| behavior (entry/exit)</para> |
| </listitem> |
| </itemizedlist> Note that the function itself can take up to 5 |
| arguments.</para> |
| <para>Example:</para> |
| <para> |
| <programlisting>MSM_EUML_FUNCTION(BinarySearch_,std::binary_search,binary_search_,bool,bool)</programlisting> |
| </para> |
| <para>Can be used like:</para> |
| <para> |
| <programlisting>binary_search_(begin_(fsm_(m_var)),end_(fsm_(m_var)),Int_<9>())</programlisting> |
| </para> |
| </refsect3> |
| <refsect3> |
| <title>MSM_EUML_METHOD</title> |
| <para>This macro creates a eUML function and a functor for use with the |
| functor front-end, based on a method:<itemizedlist> |
| <listitem> |
| <para>first parameter: the name of the functor</para> |
| </listitem> |
| <listitem> |
| <para>second parameter: the underlying function</para> |
| </listitem> |
| <listitem> |
| <para>third parameter: the eUML function name</para> |
| </listitem> |
| <listitem> |
| <para>fourth parameter: the return type if used in a transition |
| behavior</para> |
| </listitem> |
| <listitem> |
| <para>fifth parameter: the return type if used in a state |
| behavior (entry/exit)</para> |
| </listitem> |
| </itemizedlist> Note that the method itself can take up to 4 arguments |
| (5 like for a free function - 1 for the object on which the method is |
| called).</para> |
| <para>Example:</para> |
| <programlisting>struct Empty : public msm::front::state<> , public euml_state<Empty> |
| { |
| void activate_empty() {std::cout << "switching to Empty " << std::endl;} |
| ... |
| }; |
| MSM_EUML_METHOD(ActivateEmpty_,activate_empty,activate_empty_,void,void)</programlisting> |
| <para>Can be used like:</para> |
| <para> |
| <programlisting>Empty == Open + open_close / (close_drawer , activate_empty_(target_))</programlisting> |
| </para> |
| </refsect3> |
| <refsect3> |
| <title>BOOST_MSM_EUML_ACTION(action-instance-name)</title> |
| <para>This macro declares a behavior type and a const instance for use in |
| state or transition behaviors. The action implementation itself follows |
| the macro declaration, for example:</para> |
| <programlisting>BOOST_MSM_EUML_ACTION(good_disk_format) |
| { |
| template <class Fsm,class Evt,class SourceState,class TargetState> |
| void/bool operator()(Evt const& evt,Fsm&,SourceState& ,TargetState& ){...} |
| };</programlisting> |
| </refsect3> |
| <refsect3> |
| <title>BOOST_MSM_EUML_FLAG(flag-instance-name)</title> |
| <para>This macro declares a flag type and a const instance for use in |
| behaviors.</para> |
| </refsect3> |
| <refsect3> |
| <title>BOOST_MSM_EUML_FLAG_NAME(flag-instance-name)</title> |
| <para>This macro returns the name of the flag type generated by |
| BOOST_MSM_EUML_FLAG. You need this where the type is required (usually |
| with the back-end method is_flag_active). For example:</para> |
| <programlisting>fsm.is_flag_active<BOOST_MSM_EUML_FLAG_NAME(CDLoaded)>()</programlisting> |
| </refsect3> |
| <refsect3> |
| <title>BOOST_MSM_EUML_DECLARE_ATTRIBUTE(event-type,event-name)</title> |
| <para>This macro declares an attribute called event-name of type event-type. |
| This attribute can then be made part of an attribute list using |
| BOOST_MSM_EUML_ATTRIBUTES.</para> |
| </refsect3> |
| <refsect3> |
| <title>BOOST_MSM_EUML_ATTRIBUTES(attributes-expression,attributes-name)</title> |
| <para>This macro declares an attribute list called attributes-name based on |
| the expression as first argument. These attributes can then be made part |
| of an event using BOOST_MSM_EUML_EVENT_WITH_ATTRIBUTES, of a state as |
| 3rd parameter of BOOST_MSM_EUML_STATE or of a state machine as 5th |
| parameter of BOOST_MSM_EUML_DECLARE_STATE_MACHINE.</para> |
| <para>Attributes are added using left-shift, for example:</para> |
| <programlisting>// m_song is of type std::string |
| BOOST_MSM_EUML_DECLARE_ATTRIBUTE(std::string,m_song) |
| // contains one attribute, m_song |
| BOOST_MSM_EUML_ATTRIBUTES((attributes_ << m_song ), FoundDef)</programlisting> |
| </refsect3> |
| <refsect3> |
| <title>BOOST_MSM_EUML_EVENT(event-instance name)</title> |
| <para>This macro defines an event type (event-instance-name_helper) and |
| declares a const instance of this event type called event-instance-name |
| for use in a transition table or state behaviors.</para> |
| </refsect3> |
| <refsect3> |
| <title>BOOST_MSM_EUML_EVENT_WITH_ATTRIBUTES(event-instance-name,attributes)</title> |
| <para>This macro defines an event type (event-instance-name_helper) and |
| declares a const instance of this event type called event-instance-name |
| for use in a transition table or state behaviors. The event will have as |
| attributes the ones passed by the second argument:</para> |
| <para><code>BOOST_MSM_EUML_EVENT_WITH_ATTRIBUTES(Found,FoundDef)</code> |
| </para> |
| <para>The created event instance supports operator()(attributes) so that |
| <programlisting>my_back_end.process_event(Found(some_string))</programlisting> |
| is possible.</para> |
| </refsect3> |
| <refsect3> |
| <title>BOOST_MSM_EUML_EVENT_NAME(event-instance-name)</title> |
| <para>This macro returns the name of the event type generated by |
| BOOST_MSM_EUML_EVENT or BOOST_MSM_EUML_EVENT_WITH_ATTRIBUTES. You need |
| this where the type is required (usually inside a back-end definition). |
| For example:</para> |
| <para> |
| <programlisting>typedef msm::back::state_machine<Playing_, |
| msm::back::ShallowHistory<mpl::vector<BOOST_MSM_EUML_EVENT_NAME(end_pause) |
| > > > Playing_type;</programlisting> |
| </para> |
| </refsect3> |
| <refsect3> |
| <title>BOOST_MSM_EUML_STATE(build-expression,state-instance-name)</title> |
| <para>This macro defines a state type (state-instance-name_helper) and |
| declares a const instance of this state type called state-instance-name |
| for use in a transition table or state behaviors.</para> |
| <para>There are several possibilitites for the expression syntax:<itemizedlist> |
| <listitem> |
| <para>(): state without entry or exit action.</para> |
| </listitem> |
| <listitem> |
| <para>(Expr1): state with entry but no exit action.</para> |
| </listitem> |
| <listitem> |
| <para>(Expr1,Expr2): state with entry and exit action.</para> |
| </listitem> |
| <listitem> |
| <para>(Expr1,Expr2,Attributes): state with entry and exit |
| action, defining some attributes.</para> |
| </listitem> |
| <listitem> |
| <para>(Expr1,Expr2,Attributes,Configure): state with entry and |
| exit action, defining some attributes and flags (standard |
| MSM flags) or deferred events (standard MSM deferred |
| events).</para> |
| </listitem> |
| <listitem> |
| <para>(Expr1,Expr2,Attributes,Configure,Base): state with entry |
| and exit action, defining some attributes, flags and |
| deferred events (plain msm deferred events) and a |
| non-default base state (as defined in standard MSM).</para> |
| </listitem> |
| </itemizedlist></para> |
| </refsect3> |
| <refsect3> |
| <title>BOOST_MSM_EUML_INTERRUPT_STATE(build-expression,state-instance-name)</title> |
| <para>This macro defines an interrupt state type |
| (state-instance-name_helper) and declares a const instance of this state |
| type called state-instance-name for use in a transition table or state |
| behaviors.</para> |
| <para>There are several possibilitites for the expression syntax. In all of |
| them, the first argument is the name of the event (generated by one of |
| the previous macros) ending the interrupt:<itemizedlist> |
| <listitem> |
| <para>(end_interrupt_event): interrupt state without entry or |
| exit action.</para> |
| </listitem> |
| <listitem> |
| <para>(end_interrupt_event,Expr1): interrupt state with entry |
| but no exit action.</para> |
| </listitem> |
| <listitem> |
| <para>(end_interrupt_event,Expr1,Expr2): interrupt state with |
| entry and exit action.</para> |
| </listitem> |
| <listitem> |
| <para>(end_interrupt_event,Expr1,Expr2,Attributes): interrupt |
| state with entry and exit action, defining some |
| attributes.</para> |
| </listitem> |
| <listitem> |
| <para>(end_interrupt_event,Expr1,Expr2,Attributes,Configure): |
| interrupt state with entry and exit action, defining some |
| attributes and flags (standard MSM flags) or deferred events |
| (standard MSM deferred events).</para> |
| </listitem> |
| <listitem> |
| <para>(end_interrupt_event,Expr1,Expr2,Attributes,Configure,Base): |
| interrupt state with entry and exit action, defining some |
| attributes, flags and deferred events (plain msm deferred |
| events) and a non-default base state (as defined in standard |
| MSM).</para> |
| </listitem> |
| </itemizedlist></para> |
| </refsect3> |
| <refsect3> |
| <title>BOOST_MSM_EUML_TERMINATE_STATE(build-expression,state-instance-name)</title> |
| <para>This macro defines a terminate pseudo-state type |
| (state-instance-name_helper) and declares a const instance of this state |
| type called state-instance-name for use in a transition table or state |
| behaviors.</para> |
| <para>There are several possibilitites for the expression syntax:<itemizedlist> |
| <listitem> |
| <para>(): terminate pseudo-state without entry or exit |
| action.</para> |
| </listitem> |
| <listitem> |
| <para>(Expr1): terminate pseudo-state with entry but no exit |
| action.</para> |
| </listitem> |
| <listitem> |
| <para>(Expr1,Expr2): terminate pseudo-state with entry and exit |
| action.</para> |
| </listitem> |
| <listitem> |
| <para>(Expr1,Expr2,Attributes): terminate pseudo-state with |
| entry and exit action, defining some attributes.</para> |
| </listitem> |
| <listitem> |
| <para>(Expr1,Expr2,Attributes,Configure): terminate pseudo-state |
| with entry and exit action, defining some attributes and |
| flags (standard MSM flags) or deferred events (standard MSM |
| deferred events).</para> |
| </listitem> |
| <listitem> |
| <para>(Expr1,Expr2,Attributes,Configure,Base): terminate |
| pseudo-state with entry and exit action, defining some |
| attributes, flags and deferred events (plain msm deferred |
| events) and a non-default base state (as defined in standard |
| MSM).</para> |
| </listitem> |
| </itemizedlist></para> |
| </refsect3> |
| <refsect3> |
| <title>BOOST_MSM_EUML_EXIT_STATE(build-expression,state-instance-name)</title> |
| <para>This macro defines an exit pseudo-state type |
| (state-instance-name_helper) and declares a const instance of this state |
| type called state-instance-name for use in a transition table or state |
| behaviors.</para> |
| <para>There are several possibilitites for the expression syntax:<itemizedlist> |
| <listitem> |
| <para>(forwarded_event):exit pseudo-state without entry or exit |
| action.</para> |
| </listitem> |
| <listitem> |
| <para>(forwarded_event,Expr1): exit pseudo-state with entry but |
| no exit action.</para> |
| </listitem> |
| <listitem> |
| <para>(forwarded_event,Expr1,Expr2): exit pseudo-state with |
| entry and exit action.</para> |
| </listitem> |
| <listitem> |
| <para>(forwarded_event,Expr1,Expr2,Attributes): exit |
| pseudo-state with entry and exit action, defining some |
| attributes.</para> |
| </listitem> |
| <listitem> |
| <para>(forwarded_event,Expr1,Expr2,Attributes,Configure): exit |
| pseudo-state with entry and exit action, defining some |
| attributes and flags (standard MSM flags) or deferred events |
| (standard MSM deferred events).</para> |
| </listitem> |
| <listitem> |
| <para>(forwarded_event,Expr1,Expr2,Attributes,Configure,Base): |
| exit pseudo-state with entry and exit action, defining some |
| attributes, flags and deferred events (plain msm deferred |
| events) and a non-default base state (as defined in standard |
| MSM).</para> |
| </listitem> |
| </itemizedlist></para> |
| <para>Note that the forwarded_event must be constructible from the event |
| sent by the submachine containing the exit point.</para> |
| </refsect3> |
| <refsect3> |
| <title>BOOST_MSM_EUML_ENTRY_STATE(int |
| region-index,build-expression,state-instance-name)</title> |
| <para>This macro defines an entry pseudo-state type |
| (state-instance-name_helper) and declares a const instance of this state |
| type called state-instance-name for use in a transition table or state |
| behaviors.</para> |
| <para>There are several possibilitites for the expression syntax:<itemizedlist> |
| <listitem> |
| <para>(): entry pseudo-state without entry or exit |
| action.</para> |
| </listitem> |
| <listitem> |
| <para>(Expr1): entry pseudo-state with entry but no exit |
| action.</para> |
| </listitem> |
| <listitem> |
| <para>(Expr1,Expr2): entry pseudo-state with entry and exit |
| action.</para> |
| </listitem> |
| <listitem> |
| <para>(Expr1,Expr2,Attributes): entry pseudo-state with entry |
| and exit action, defining some attributes.</para> |
| </listitem> |
| <listitem> |
| <para>(Expr1,Expr2,Attributes,Configure): entry pseudo-state |
| with entry and exit action, defining some attributes and |
| flags (standard MSM flags) or deferred events (standard MSM |
| deferred events).</para> |
| </listitem> |
| <listitem> |
| <para>(Expr1,Expr2,Attributes,Configure,Base): entry |
| pseudo-state with entry and exit action, defining some |
| attributes, flags and deferred events (plain msm deferred |
| events) and a non-default base state (as defined in standard |
| MSM).</para> |
| </listitem> |
| </itemizedlist></para> |
| </refsect3> |
| <refsect3> |
| <title>BOOST_MSM_EUML_EXPLICIT_ENTRY_STATE(int |
| region-index,build-expression,state-instance-name)</title> |
| <para>This macro defines a submachine's substate type |
| (state-instance-name_helper), which can be explicitly entered and also |
| declares a const instance of this state type called state-instance-name |
| for use in a transition table or state behaviors.</para> |
| <para>There are several possibilitites for the expression syntax:<itemizedlist> |
| <listitem> |
| <para>(): state without entry or exit action.</para> |
| </listitem> |
| <listitem> |
| <para>(Expr1): state with entry but no exit action.</para> |
| </listitem> |
| <listitem> |
| <para>(Expr1,Expr2): state with entry and exit action.</para> |
| </listitem> |
| <listitem> |
| <para>(Expr1,Expr2,Attributes): state with entry and exit |
| action, defining some attributes.</para> |
| </listitem> |
| <listitem> |
| <para>(Expr1,Expr2,Attributes,Configure): state with entry and |
| exit action, defining some attributes and flags (standard |
| MSM flags) or deferred events (standard MSM deferred |
| events).</para> |
| </listitem> |
| <listitem> |
| <para>(Expr1,Expr2,Attributes,Configure,Base): state with entry |
| and exit action, defining some attributes, flags and |
| deferred events (plain msm deferred events) and a |
| non-default base state (as defined in standard MSM).</para> |
| </listitem> |
| </itemizedlist></para> |
| </refsect3> |
| <refsect3> |
| <title>BOOST_MSM_EUML_STATE_NAME(state-instance-name)</title> |
| <para>This macro returns the name of the state type generated by |
| BOOST_MSM_EUML_STATE or other state macros. You need this where the type |
| is required (usually using a backend function). For example:</para> |
| <para> |
| <programlisting>fsm.get_state<BOOST_MSM_EUML_STATE_NAME(StringFind)&>().some_state_function();</programlisting> |
| </para> |
| </refsect3> |
| <refsect3> |
| <title>BOOST_MSM_EUML_DECLARE_STATE(build-expression,state-instance-name)</title> |
| <para>Like BOOST_MSM_EUML_STATE but does not provide an instance, simply a |
| type declaration.</para> |
| </refsect3> |
| <refsect3> |
| <title>BOOST_MSM_EUML_DECLARE_INTERRUPT_STATE(build-expression,state-instance-name)</title> |
| <para>Like BOOST_MSM_EUML_INTERRUPT_STATE but does not provide an instance, |
| simply a type declaration.</para> |
| </refsect3> |
| <refsect3> |
| <title>BOOST_MSM_EUML_DECLARE_TERMINATE_STATE(build-expression,state-instance-name)</title> |
| <para>Like BOOST_MSM_EUML_TERMINATE_STATE but does not provide an instance, |
| simply a type declaration.</para> |
| </refsect3> |
| <refsect3> |
| <title>BOOST_MSM_EUML_DECLARE_EXIT_STATE(build-expression,state-instance-name)</title> |
| <para>Like BOOST_MSM_EUML_EXIT_STATE but does not provide an instance, |
| simply a type declaration.</para> |
| </refsect3> |
| <refsect3> |
| <title>BOOST_MSM_EUML_DECLARE_ENTRY_STATE(int |
| region-index,build-expression,state-instance-name)</title> |
| <para>Like BOOST_MSM_EUML_ENTRY_STATE but does not provide an instance, |
| simply a type declaration.</para> |
| </refsect3> |
| <refsect3> |
| <title>BOOST_MSM_EUML_DECLARE_EXPLICIT_ENTRY_STATE(int |
| region-index,build-expression,state-instance-name)</title> |
| <para>Like BOOST_MSM_EUML_EXPLICIT_ENTRY_STATE but does not provide an |
| instance, simply a type declaration.</para> |
| </refsect3> |
| <refsect3> |
| <title>BOOST_MSM_EUML_TRANSITION_TABLE(expression, |
| table-instance-name)</title> |
| <para>This macro declares a transition table type and also declares a const |
| instance of the table which can then be used in a state machine |
| declaration (see BOOST_MSM_EUML_DECLARE_STATE_MACHINE).The expression |
| must follow the <command xlink:href="#reference-stt-grammar">transition |
| table grammar</command>.</para> |
| </refsect3> |
| <refsect3> |
| <title>BOOST_MSM_EUML_DECLARE_TRANSITION_TABLE(iexpression,table-instance-name)</title> |
| <para>Like BOOST_MSM_EUML_TRANSITION_TABLE but does not provide an instance, |
| simply a type declaration.</para> |
| </refsect3> |
| <refsect3> |
| <title>BOOST_MSM_EUML_INTERNAL_TRANSITION_TABLE(expression, |
| table-instance-name)</title> |
| <para>This macro declares a transition table type and also declares a const |
| instance of the table.The expression must follow the <command |
| xlink:href="#reference-stt-grammar">transition table |
| grammar</command>. For the moment, this macro is not used.</para> |
| </refsect3> |
| <refsect3> |
| <title>BOOST_MSM_EUML_DECLARE_INTERNAL_TRANSITION_TABLE(iexpression,table-instance-name)</title> |
| <para>Like BOOST_MSM_EUML_TRANSITION_TABLE but does not provide an instance, |
| simply a type declaration. This is currently the only way to declare an |
| internal transition table with eUML. For example:</para> |
| <programlisting>BOOST_MSM_EUML_DECLARE_STATE((Open_Entry,Open_Exit),Open_def) |
| struct Open_impl : public Open_def |
| { |
| BOOST_MSM_EUML_DECLARE_INTERNAL_TRANSITION_TABLE(( |
| open_close [internal_guard1] / internal_action1 , |
| open_close [internal_guard2] / internal_action2 |
| )) |
| }; </programlisting> |
| </refsect3> |
| </refsect2> |
| </refsect1> |
| </refentry> |
| </part> |
| </book> |