| <html><head> |
| <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> |
| <title>Back-end</title><link rel="stylesheet" href="boostbook.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="index.html" title="Meta State Machine (MSM) V2.12"><link rel="up" href="ch03.html" title="Chapter 3. Tutorial"><link rel="prev" href="ch03s04.html" title="eUML (experimental)"><link rel="next" href="ch04.html" title="Chapter 4. Performance / Compilers"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Back-end</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="ch03s04.html">Prev</a> </td><th width="60%" align="center">Chapter 3. Tutorial</th><td width="20%" align="right"> <a accesskey="n" href="ch04.html">Next</a></td></tr></table><hr></div><div class="sect1" title="Back-end"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e2123"></a>Back-end</h2></div></div></div><p>There is, at the moment, one back-end. This back-end contains the library |
| engine and defines the performance and functionality 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.</p><div class="sect2" title="Creation"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2128"></a>Creation </h3></div></div></div><p>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: |
| </p><pre class="programlisting">typedef msm::back::state_machine<my_front_end> my_fsm;</pre><p>We now have a fully functional state machine type. The next sections will |
| describe what can be done with it.</p></div><div class="sect2" title="Starting a state machine"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2137"></a><span class="command"><strong><a name="backend-start"></a></strong></span>Starting a state machine</h3></div></div></div><p>The <code class="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 <a class="link" href="examples/iPodSearch.cpp" target="_top">iPodSearch</a> example uses this possibility.</p></div><div class="sect2" title="Event dispatching"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2149"></a>Event dispatching</h3></div></div></div><p>The main reason to exist for a state machine is to dispatch events. For |
| MSM, events are objects of a given event type. The object itself can contain |
| data, but the event type is what decides of the transition to be taken. For |
| MSM, if some_event is a given type (a simple struct for example) and e1 and |
| e2 concrete 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: </p><pre class="programlisting">my_fsm fsm; fsm.process_event(some_event()); |
| some_event e1; fsm.process_event(e1)</pre><p>Creating an event on the fly will be optimized by the compiler so the |
| performance will not degrade.</p></div><div class="sect2" title="Active state(s)"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2158"></a>Active state(s)</h3></div></div></div><p>The backend also offers a way to know which state is active, though you |
| will normally only need this for debugging purposes. If what you need simply |
| is doing something with the active state, <span class="command"><strong><a class="command" href="ch02s02.html#UML-internal-transition">internal transitions</a></strong></span> or |
| <span class="command"><strong><a class="command" href="ch03s05.html#backend-visitor">visitors</a></strong></span> are a better |
| alternative. If you need to know what state is active, const int* |
| current_state() will return an array of state ids. Please refer to the |
| <span class="command"><strong><a class="command" href="ch06s03.html#internals-state-id">internals section</a></strong></span> to |
| know how state ids are generated.</p></div><div class="sect2" title="Serialization"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2172"></a><span class="command"><strong><a name="back-end-serialization"></a></strong></span>Serialization</h3></div></div></div><p>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 class="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:</p><p> |
| </p><pre class="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; |
| } </pre><p> |
| </p><p>Loading back is very similar:</p><p> |
| </p><pre class="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; |
| } </pre><p> |
| </p><p>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:</p><p> |
| </p><pre class="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; |
| }; </pre><p> |
| </p><p>You can also serialize data contained in the front-end class. Again, you |
| need to provide the typedef and implement serialize:</p><p> |
| </p><pre class="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; |
| } |
| ... |
| }; </pre><p> |
| </p><p>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 class="code">BOOST_MSM_EUML_STATE</code> cannot be used, so the state will have |
| to be implemented by directly inheriting from |
| <code class="code">front::euml::euml_state</code>.</p><p>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).</p><p>This <a class="link" href="examples/Serialize.cpp" target="_top">example</a> shows a state machine which we serialize after processing an |
| event. The <code class="code">Empty</code> state also has some data to serialize.</p></div><div class="sect2" title="Base state type"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2225"></a><span class="command"><strong><a name="backend-base-state"></a></strong></span>Base state type </h3></div></div></div><p>Sometimes, one needs to customize states to avoid repetition and provide a |
| common functionality, for example in the form of a virtual method. You might |
| also want to make your states polymorphic so that you can call typeid on |
| them for logging or debugging. It is also useful if you need a visitor, like |
| the next section will show. You will notice that all front-ends offer the |
| possibility of adding a base type. 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:</p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>Add the non-default base state in your msm::front::state<> |
| definition, as first template argument (except for |
| interrupt_states for which it is the second argument, the first |
| one being the event ending the interrupt), for example, |
| my_base_state being your new base state for all states in a |
| given state machine: |
| </p><pre class="programlisting">struct Empty : public msm::front::state<my_base_state></pre><p> |
| 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 class="code">msm::front::polymorphic_state</code> |
| </p></li><li class="listitem"><p>Add the user-defined base state in the state machine frontend |
| definition, as a second template argument, for example: |
| </p><pre class="programlisting">struct player_ : public msm::front::state_machine<player_,my_base_state> </pre></li></ul></div><p>You can also ask for a state with a given id (which you might have gotten |
| from current_state()) using <code class="code">const base_state* get_state_by_id(int id) |
| const</code> where base_state is the one you just defined. You can now |
| do something polymorphically.</p></div><div class="sect2" title="Visitor"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2251"></a><span class="command"><strong><a name="backend-visitor"></a></strong></span>Visitor</h3></div></div></div><p>In some cases, having a pointer-to-base of the currently active states is |
| not enough. You might want to call non-virtually a method of the currently |
| active states. It will not be said that MSM forces the virtual keyword down |
| your throat!</p><p>To achieve this goal, MSM provides its own variation of a visitor pattern |
| using the previously described user-defined state technique. If you add to |
| your user-defined base state an <code class="code">accept_sig</code> typedef giving the |
| return value (unused for the moment) and 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:</p><pre class="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 {} |
| };</pre><p>This makes your states polymorphic and visitable. In this case, accept is |
| made const and takes no argument. It could also be:</p><pre class="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 {} |
| };</pre><p>And now, <code class="code">accept</code> will take one argument (it could also be |
| non-const). By default, <code class="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:</p><pre class="programlisting">#define BOOST_MSM_VISITOR_ARG_SIZE 3 |
| #include <boost/msm/back/state_machine.hpp></pre><p>Note that accept will be called on ALL active states <span class="underline">and also automatically on sub-states of a |
| submachine</span>.</p><p><span class="underline">Important warning</span>: The method |
| visit_current_states takes its parameter by value, so if the signature of |
| the accept function is to contain a parameter passed by reference, pass this |
| parameter with a boost:ref/cref to avoid undesired copies or slicing. So, |
| for example, in the above case, call:</p><pre class="programlisting">SomeVisitor vis; sm.visit_current_states(boost::ref(vis));</pre><p>This <a class="link" href="examples/SM-2Arg.cpp" target="_top">example</a> uses a |
| visiting function with 2 arguments.</p></div><div class="sect2" title="Flags"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2294"></a>Flags</h3></div></div></div><p>Flags is a MSM-only concept, supported by all front-ends, which base |
| themselves on the functions: </p><pre class="programlisting">template <class Flag> bool is_flag_active() |
| template <class Flag,class BinaryOp> bool is_flag_active()</pre><p>These functions return true if the currently active state(s) support the |
| Flag property. The first variant ORs the result if there are several |
| orthogonal regions, the second one expects OR or AND, for example:</p><pre class="programlisting">my_fsm.is_flag_active<MyFlag>() |
| my_fsm.is_flag_active<MyFlag,my_fsm_type::Flag_OR>()</pre><p>Please refer to the front-ends sections for usage examples.</p></div><div class="sect2" title="Getting a state"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2307"></a>Getting a state</h3></div></div></div><p>It is sometimes necessary to have the client code get access to the |
| states' data. After all, the states are created once for good and hang |
| around as long as the state machine does so why not use it? You simply just |
| need sometimes to get information about any state, even inactive ones. An |
| example is if you want to write a coverage tool and know how many times a |
| state was visited. To get a state, use the get_state method giving the state |
| name, for example: </p><pre class="programlisting">player::Stopped* tempstate = p.get_state<player::Stopped*>();</pre><p> or </p><pre class="programlisting">player::Stopped& tempstate2 = p.get_state<player::Stopped&>();</pre><p>depending on your personal taste. </p></div><div class="sect2" title="State machine constructor with arguments"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2320"></a><span class="command"><strong><a name="backend-fsm-constructor-args"></a></strong></span> State machine constructor with arguments </h3></div></div></div><p>You might want to define a state machine with a non-default constructor. |
| For example, you might want to write: </p><pre class="programlisting">struct player_ : public msm::front::state_machine_def<player_> |
| { |
| player_(int some_value){…} |
| }; </pre><p>This is possible, using the back-end as forwarding object: </p><pre class="programlisting">typedef msm::back::state_machine<player_ > player; player p(3);</pre><p>The back-end will call the corresponding front-end constructor upon |
| creation.</p><p>You can pass arguments up to the value of the |
| BOOST_MSM_CONSTRUCTOR_ARG_SIZE macro (currently 5) arguments. Change this |
| value before including any header if you need to overwrite the default. </p><p>You can also pass arguments by reference (or const-reference) using |
| boost::ref (or boost::cref):</p><pre class="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); |
| </pre><p>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:</p><pre class="programlisting">player p( back::states_ << state_1 << ... << state_n , boost::ref(data),3);</pre><p>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:</p><pre class="programlisting">player p( back::states_ << Playing(back::states_ << Song1(some_Song1_data)) , |
| boost::ref(data),3);</pre><p>It is also possible to replace a given state by a new instance at any time |
| using <code class="code">set_states()</code> and the same syntax, for example: |
| </p><pre class="programlisting">p.set_states( back::states_ << state_1 << ... << state_n );</pre><p>An <a class="link" href="examples/Constructor.cpp" target="_top">example</a> making intensive use of this capability is provided.</p></div><div class="sect2" title="Trading run-time speed for better compile-time / multi-TU compilation"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2360"></a><span class="command"><strong><a name="backend-tradeof-rt-ct"></a></strong></span>Trading run-time speed for |
| better compile-time / multi-TU compilation</h3></div></div></div><p>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:</p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>many transition conflicts</p></li><li class="listitem"><p>submachines</p></li></ul></div><p>The back-end <code class="code">msm::back::state_machine</code> has a third template |
| argument (first is the front-end, second is the history policy) defaulting |
| to <code class="code">favor_runtime_speed</code>. To switch to |
| <code class="code">favor_compile_time</code>, which is declared in |
| <code class="code"><msm/back/favor_compile_time.hpp></code>, you need to:</p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>switch the policy to <code class="code">favor_compile_time</code> for the |
| main state machine (and possibly submachines)</p></li><li class="listitem"><p>move the submachine declarations into their own header which |
| includes |
| <code class="code"><msm/back/favor_compile_time.hpp></code></p></li><li class="listitem"><p>add for each submachine a cpp file including your header and |
| calling a macro, which generates helper code, for |
| example:</p><pre class="programlisting">#include "mysubmachine.hpp" |
| BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(mysubmachine)</pre></li><li class="listitem"><p>configure your compiler for multi-core compilation</p></li></ul></div><p>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.</p><p>Independently, transition conflicts resolution will also be much |
| faster.</p><p>This policy uses boost.any behind the hood, which means that we will lose |
| one feature which MSM offers with the default policy, <a class="link" href="ch03s02.html#event-hierarchy">event hierarchy</a>. The following |
| example takes our iPod example and speeds up compile-time by using this |
| technique. We have:</p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p><a class="link" href="examples/iPod_distributed/iPod.cpp" target="_top">our main |
| state machine and main function</a></p></li><li class="listitem"><p><a class="link" href="examples/iPod_distributed/PlayingMode.hpp" target="_top">PlayingMode moved to a separate header</a></p></li><li class="listitem"><p><a class="link" href="examples/iPod_distributed/PlayingMode.cpp" target="_top">a |
| cpp for PlayingMode</a></p></li><li class="listitem"><p><a class="link" href="examples/iPod_distributed/MenuMode.hpp" target="_top">MenuMode moved to a separate header</a></p></li><li class="listitem"><p><a class="link" href="examples/iPod_distributed/MenuMode.cpp" target="_top">a |
| cpp for MenuMode</a></p></li><li class="listitem"><p><a class="link" href="examples/iPod_distributed/Events.hpp" target="_top">events |
| move to a separate header as all machines use |
| it</a></p></li></ul></div><p> |
| </p></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="ch03s04.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="ch03.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="ch04.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">eUML (experimental) </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> Chapter 4. Performance / Compilers</td></tr></table></div></body></html> |