• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<html><head>
2      <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
3   <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)"><link rel="up" href="ch03.html" title="Chapter&nbsp;3.&nbsp;Tutorial"><link rel="prev" href="ch03s04.html" title="eUML"><link rel="next" href="ch04.html" title="Chapter&nbsp;4.&nbsp; 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>&nbsp;</td><th width="60%" align="center">Chapter&nbsp;3.&nbsp;Tutorial</th><td width="20%" align="right">&nbsp;<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="d0e2298"></a>Back-end</h2></div></div></div><p>There is, at the moment, one back-end. This back-end contains the library
4                    engine and defines the performance and functionality trade-offs. The currently
5                    available back-end implements most of the functionality defined by the UML 2.0
6                    standard at very high runtime speed, in exchange for longer compile-time. The
7                    runtime speed is due to a constant-time double-dispatch and self-adapting
8                    capabilities allowing the framework to adapt itself to the features used by a
9                    given concrete state machine. All unneeded features either disable themselves or
10                    can be manually disabled. See section 5.1 for a complete description of the
11                    run-to-completion algorithm.</p><div class="sect2" title="Creation"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2303"></a>Creation </h3></div></div></div><p>MSM being divided between front and back-end, one needs to first define a
12                        front-end. Then, to create a real state machine, the back-end must be
13                        declared:
14                        </p><pre class="programlisting">typedef msm::back::state_machine&lt;my_front_end&gt; my_fsm;</pre><p>We now have a fully functional state machine type. The next sections will
15                        describe what can be done with it.</p></div><div class="sect2" title="Starting and stopping a state machine"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2312"></a><span class="command"><strong><a name="backend-start"></a></strong></span>Starting and stopping a state
16                        machine</h3></div></div></div><p>The <code class="code">start()</code> method starts the state machine, meaning it will
17                        activate the initial state, which means in turn that the initial state's
18                        entry behavior will be called. We need the start method because you do not
19                        always want the entry behavior of the initial state to be called immediately
20                        but only when your state machine is ready to process events. A good example
21                        of this is when you use a state machine to write an algorithm and each loop
22                        back to the initial state is an algorithm call. Each call to start will make
23                        the algorithm run once. The <a class="link" href="examples/iPodSearch.cpp" target="_top">iPodSearch</a> example uses this possibility.</p><p>The <code class="code">stop()</code> method works the same way. It will cause the exit
24                        actions of the currently active states(s) to be called.</p><p>Both methods are actually not an absolute need. Not calling them will
25                        simply cause your first entry or your last exit action not to be
26                        called.</p></div><div class="sect2" title="Event dispatching"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2331"></a>Event dispatching</h3></div></div></div><p>The main reason to exist for a state machine is to dispatch events. For
27                        MSM, events are objects of a given event type. The object itself can contain
28                        data, but the event type is what decides of the transition to be taken. For
29                        MSM, if some_event is a given type (a simple struct for example) and e1 and
30                        e2 concrete instances of some_event, e1 and e2 are equivalent, from a
31                        transition perspective. Of course, e1 and e2 can have different values and
32                        you can use them inside actions. Events are dispatched as const reference,
33                        so actions cannot modify events for obvious side-effect reasons. To dispatch
34                        an event of type some_event, you can simply create one on the fly or
35                        instantiate if before processing: </p><pre class="programlisting">my_fsm fsm; fsm.process_event(some_event());
36some_event e1; fsm.process_event(e1)</pre><p>Creating an event on the fly will be optimized by the compiler so the
37                        performance will not degrade.</p></div><div class="sect2" title="Active state(s)"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2340"></a>Active state(s)</h3></div></div></div><p>The backend also offers a way to know which state is active, though you
38                        will normally only need this for debugging purposes. If what you need simply
39                        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
40                            <span class="command"><strong><a class="command" href="ch03s05.html#backend-visitor">visitors</a></strong></span> are a better
41                        alternative. If you need to know what state is active, const int*
42                        current_state() will return an array of state ids. Please refer to the
43                            <span class="command"><strong><a class="command" href="ch06s03.html#internals-state-id">internals section</a></strong></span> to
44                        know how state ids are generated.</p></div><div class="sect2" title="Serialization"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2354"></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
45                        different time. MSM supports this feature for the basic and functor
46                        front-ends, and in a more limited manner for eUML. MSM supports
47                        boost::serialization out of the box (by offering a <code class="code">serialize</code>
48                        function). Actually, for basic serialization, you need not do much, a MSM
49                        state machine is serializable almost like any other type. Without any
50                        special work, you can make a state machine remember its state, for
51                        example:</p><p>
52                        </p><pre class="programlisting">MyFsm fsm;
53// write to archive
54std::ofstream ofs("fsm.txt");
55// save fsm to archive
56{
57    boost::archive::text_oarchive oa(ofs);
58    // write class instance to archive
59    oa &lt;&lt; fsm;
60}                                                  </pre><p>
61                    </p><p>Loading back is very similar:</p><p>
62                        </p><pre class="programlisting">MyFsm fsm;
63{
64    // create and open an archive for input
65    std::ifstream ifs("fsm.txt");
66    boost::archive::text_iarchive ia(ifs);
67    // read class state from archive
68    ia &gt;&gt; fsm;
69}                                          </pre><p>
70                    </p><p>This will (de)serialize the state machine itself but not the concrete
71                        states' data. This can be done on a per-state basis to reduce the amount of
72                        typing necessary. To allow serialization of a concrete state, provide a
73                        do_serialize typedef and implement the serialize function:</p><p>
74                        </p><pre class="programlisting">struct Empty : public msm::front::state&lt;&gt;
75{
76    // we want Empty to be serialized. First provide the typedef
77    typedef int do_serialize;
78    // then implement serialize
79    template&lt;class Archive&gt;
80    void serialize(Archive &amp; ar, const unsigned int /* version */)
81    {
82        ar &amp; some_dummy_data;
83    }
84    Empty():some_dummy_data(0){}
85    int some_dummy_data;
86};                        </pre><p>
87                    </p><p>You can also serialize data contained in the front-end class. Again, you
88                        need to provide the typedef and implement serialize:</p><p>
89                        </p><pre class="programlisting">struct player_ : public msm::front::state_machine_def&lt;player_&gt;
90{
91    //we might want to serialize some data contained by the front-end
92    int front_end_data;
93    player_():front_end_data(0){}
94    // to achieve this, provide the typedef
95    typedef int do_serialize;
96    // and implement serialize
97    template&lt;class Archive&gt;
98    void serialize(Archive &amp; ar, const unsigned int )
99    {
100        ar &amp; front_end_data;
101    }
102...
103};                                               </pre><p>
104                    </p><p>The saving of the back-end data (the current state(s)) is valid for all
105                        front-ends, so a front-end written using eUML can be serialized. However, to
106                        serialize a concrete state, the macros like
107                            <code class="code">BOOST_MSM_EUML_STATE</code> cannot be used, so the state will have
108                        to be implemented by directly inheriting from
109                            <code class="code">front::euml::euml_state</code>.</p><p>The only limitiation is that the event queues cannot be serialized so
110                        serializing must be done in a stable state, when no event is being
111                        processed. You can serialize during event processing only if using no queue
112                        (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
113                        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="d0e2407"></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
114                        common functionality, for example in the form of a virtual method. You might
115                        also want to make your states polymorphic so that you can call typeid on
116                        them for logging or debugging. It is also useful if you need a visitor, like
117                        the next section will show. You will notice that all front-ends offer the
118                        possibility of adding a base type. Note that all states and state machines
119                        must have the same base state, so this could reduce reuse. For example,
120                        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&lt;&gt;
121                                    definition, as first template argument (except for
122                                    interrupt_states for which it is the second argument, the first
123                                    one being the event ending the interrupt), for example,
124                                    my_base_state being your new base state for all states in a
125                                    given state machine:
126                                    </p><pre class="programlisting">struct Empty : public msm::front::state&lt;my_base_state&gt;</pre><p>
127                                    Now, my_base_state is your new base state. If it has a virtual
128                                    function, your states become polymorphic. MSM also provides a
129                                    default polymorphic base type,
130                                        <code class="code">msm::front::polymorphic_state</code>
131                                </p></li><li class="listitem"><p>Add the user-defined base state in the state machine frontend
132                                    definition, as a second template argument, for example:
133                                    </p><pre class="programlisting">struct player_ : public msm::front::state_machine&lt;player_,my_base_state&gt;             </pre></li></ul></div><p>You can also ask for a state with a given id (which you might have gotten
134                        from current_state()) using <code class="code">const base_state* get_state_by_id(int id)
135                            const</code> where base_state is the one you just defined. You can now
136                        do something polymorphically.</p></div><div class="sect2" title="Visitor"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2433"></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
137                        not enough. You might want to call non-virtually a method of the currently
138                        active states. It will not be said that MSM forces the virtual keyword down
139                        your throat!</p><p>To achieve this goal, MSM provides its own variation of a visitor pattern
140                        using the previously described user-defined state technique. If you add to
141                        your user-defined base state an <code class="code">accept_sig</code> typedef giving the
142                        return value (unused for the moment) and parameters and provide an accept
143                        method with this signature, calling visit_current_states will cause accept
144                        to be called on the currently active states. Typically, you will also want
145                        to provide an empty default accept in your base state in order in order not
146                        to force all your states to implement accept. For example your base state
147                        could be:</p><pre class="programlisting">struct my_visitable_state
148{
149   // signature of the accept function
150   typedef args&lt;void&gt; accept_sig;
151   // we also want polymorphic states
152   virtual ~my_visitable_state() {}
153   // default implementation for states who do not need to be visited
154   void accept() const {}
155};</pre><p>This makes your states polymorphic and visitable. In this case, accept is
156                        made const and takes no argument. It could also be:</p><pre class="programlisting">struct SomeVisitor {&#8230;};
157struct my_visitable_state
158{
159    // signature of the accept function
160    typedef args&lt;void,SomeVisitor&amp;&gt; accept_sig;
161    // we also want polymorphic states
162    virtual ~my_visitable_state() {}
163    // default implementation for states who do not need to be visited
164    void accept(SomeVisitor&amp;) const {}
165};</pre><p>And now, <code class="code">accept</code> will take one argument (it could also be
166                        non-const). By default, <code class="code">accept</code> takes up to 2 arguments. To get
167                        more, set #define BOOST_MSM_VISITOR_ARG_SIZE to another value before
168                        including state_machine.hpp. For example:</p><pre class="programlisting">#define BOOST_MSM_VISITOR_ARG_SIZE 3
169#include &lt;boost/msm/back/state_machine.hpp&gt;</pre><p>Note that accept will be called on ALL active states <span class="underline">and also automatically on sub-states of a
170                            submachine</span>.</p><p><span class="underline">Important warning</span>: The method
171                        visit_current_states takes its parameter by value, so if the signature of
172                        the accept function is to contain a parameter passed by reference, pass this
173                        parameter with a boost:ref/cref to avoid undesired copies or slicing. So,
174                        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
175                        visiting function with 2 arguments.</p></div><div class="sect2" title="Flags"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2476"></a>Flags</h3></div></div></div><p>Flags is a MSM-only concept, supported by all front-ends, which base
176                        themselves on the functions: </p><pre class="programlisting">template &lt;class Flag&gt; bool is_flag_active()
177template &lt;class Flag,class BinaryOp&gt; bool is_flag_active()</pre><p>These functions return true if the currently active state(s) support the
178                        Flag property. The first variant ORs the result if there are several
179                        orthogonal regions, the second one expects OR or AND, for example:</p><pre class="programlisting">my_fsm.is_flag_active&lt;MyFlag&gt;()
180my_fsm.is_flag_active&lt;MyFlag,my_fsm_type::Flag_OR&gt;()</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="d0e2489"></a>Getting a state</h3></div></div></div><p>It is sometimes necessary to have the client code get access to the
181                        states' data. After all, the states are created once for good and hang
182                        around as long as the state machine does so why not use it? You simply just
183                        need sometimes to get information about any state, even inactive ones. An
184                        example is if you want to write a coverage tool and know how many times a
185                        state was visited. To get a state, use the get_state method giving the state
186                        name, for example: </p><pre class="programlisting">player::Stopped* tempstate = p.get_state&lt;player::Stopped*&gt;();</pre><p> or </p><pre class="programlisting">player::Stopped&amp; tempstate2 = p.get_state&lt;player::Stopped&amp;&gt;();</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="d0e2502"></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.
187                        For example, you might want to write: </p><pre class="programlisting">struct player_ : public msm::front::state_machine_def&lt;player_&gt;
188{
189    player_(int some_value){&#8230;}
190}; </pre><p>This is possible, using the back-end as forwarding object: </p><pre class="programlisting">typedef msm::back::state_machine&lt;player_ &gt; player; player p(3);</pre><p>The back-end will call the corresponding front-end constructor upon
191                        creation.</p><p>You can pass arguments up to the value of the
192                        BOOST_MSM_CONSTRUCTOR_ARG_SIZE macro (currently 5) arguments. Change this
193                        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
194                        boost::ref (or boost::cref):</p><pre class="programlisting">struct player_ : public msm::front::state_machine_def&lt;player_&gt;
195{
196   player_(SomeType&amp; t, int some_value){&#8230;}
197};
198
199typedef msm::back::state_machine&lt;player_ &gt; player;
200SomeType data;
201player p(boost::ref(data),3);
202                    </pre><p>Normally, MSM default-constructs all its states or submachines. There are
203                        however cases where you might not want this. An example is when you use a
204                        state machine as submachine, and this submachine used the above defined
205                        constructors. You can add as first argument of the state machine constructor
206                        an expression where existing states are passed and copied:</p><pre class="programlisting">player p( back::states_ &lt;&lt; state_1 &lt;&lt; ... &lt;&lt; state_n , boost::ref(data),3);</pre><p>Where state_1..n are instances of some or all of the states of the state
207                        machine. Submachines being state machines, this can recurse, for example, if
208                        Playing is a submachine containing a state Song1 having itself a constructor
209                        where some data is passed:</p><pre class="programlisting">player p( back::states_ &lt;&lt; Playing(back::states_ &lt;&lt; Song1(some_Song1_data)) ,
210          boost::ref(data),3);</pre><p>It is also possible to replace a given state by a new instance at any time
211                        using <code class="code">set_states()</code> and the same syntax, for example:
212                        </p><pre class="programlisting">p.set_states( back::states_ &lt;&lt; state_1 &lt;&lt; ... &lt;&lt; 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="d0e2542"></a><span class="command"><strong><a name="backend-tradeof-rt-ct"></a></strong></span>Trading run-time speed for
213                        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.
214                        This can become a problem with older compilers and big state machines,
215                        especially if you don't really care about run-time speed that much and would
216                        be satisfied by a performance roughly the same as most state machine
217                        libraries. MSM offers a back-end policy to help there. But before you try
218                        it, if you are using a VC compiler, deactivate the /Gm compiler option
219                        (default for debug builds). This option can cause builds to be 3 times
220                        longer... If the compile-time still is a problem, read further. MSM offers a
221                        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 policy argument
222                        (first is the front-end, then the history policy) defaulting to
223                            <code class="code">favor_runtime_speed</code>. To switch to
224                            <code class="code">favor_compile_time</code>, which is declared in
225                            <code class="code">&lt;msm/back/favor_compile_time.hpp&gt;</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
226                                    main state machine (and possibly submachines)</p></li><li class="listitem"><p>move the submachine declarations into their own header which
227                                    includes
228                                    <code class="code">&lt;msm/back/favor_compile_time.hpp&gt;</code></p></li><li class="listitem"><p>add for each submachine a cpp file including your header and
229                                    calling a macro, which generates helper code, for
230                                    example:</p><pre class="programlisting">#include "mysubmachine.hpp"
231BOOST_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
232                        submachines, which will greatly speed up the compilation if you factor your
233                        state machine into smaller submachines.</p><p>Independently, transition conflicts resolution will also be much
234                        faster.</p><p>This policy uses boost.any behind the hood, which means that we will lose
235                        a feature which MSM offers with the default policy, <a class="link" href="ch03s02.html#event-hierarchy">event hierarchy</a>. The following
236                        example takes our iPod example and speeds up compile-time by using this
237                        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
238                                        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
239                                        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
240                                        cpp for MenuMode</a></p></li><li class="listitem"><p><a class="link" href="examples/iPod_distributed/Events.hpp" target="_top">events
241                                        move to a separate header as all machines use
242                                    it</a></p></li></ul></div><p>
243                    </p></div><div class="sect2" title="Compile-time state machine analysis"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2624"></a><span class="command"><strong><a name="backend-compile-time-analysis"></a></strong></span>Compile-time state machine analysis </h3></div></div></div><p>A MSM state machine being a metaprogram, it is only logical that cheking
244                        for the validity of a concrete state machine happens compile-time. To this
245                        aim, using the compile-time graph library <a class="link" href="http://www.dynagraph.org/mpl_graph/" target="_top">mpl_graph</a> (delivered at the moment
246                        with MSM) from Gordon Woodhull, MSM provides several compile-time checks:</p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>Check that orthogonal regions ar truly orthogonal.</p></li><li class="listitem"><p>Check that all states are either reachable from the initial
247                                    states or are explicit entries / pseudo-entry states.</p></li></ul></div><p>To make use of this feature, the back-end provides a policy (default is no
248                        analysis), <code class="code">msm::back::mpl_graph_fsm_check</code>. For example:</p><pre class="programlisting"> typedef msm::back::state_machine&lt; player_,msm::back::mpl_graph_fsm_check&gt; player;           </pre><p>As MSM is now using Boost.Parameter to declare policies, the policy choice
249                        can be made at any position after the front-end type (in this case
250                        <code class="code">player_</code>).</p><p>In case an error is detected, a compile-time assertion is provoked.</p><p>This feature is not enabled by default because it has a non-neglectable
251                        compile-time cost. The algorithm is linear if no explicit or pseudo entry
252                        states are found in the state machine, unfortunately still O(number of
253                        states * number of entry states) otherwise. This will be improved in future
254                        versions of MSM.</p><p>The same algorithm is also used in case you want to omit providing the
255                        region index in the <span class="command"><strong><a class="command" href="ch03s02.html#explicit-entry-no-region-id">explicit entry / pseudo entry state</a></strong></span> declaration.</p><p>The author's advice is to enable the checks after any state machine
256                        structure change and disable it again after sucessful analysis.</p><p>The <a class="link" href="examples/TestErrorOrthogonality.cpp" target="_top">following example</a> provokes an assertion if one of the first two lines
257                        of the transition table is used.</p></div><div class="sect2" title="Enqueueing events for later processing"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2668"></a><span class="command"><strong><a name="backend-enqueueing"></a></strong></span> Enqueueing events for later
258                        processing </h3></div></div></div><p>Calling <code class="code">process_event(Event const&amp;)</code> will immediately
259                        process the event with run-to-completion semantics. You can also enqueue the
260                        events and delay their processing by calling <code class="code">enqueue_event(Event
261                            const&amp;)</code> instead. Calling <code class="code">execute_queued_events()</code>
262                        will then process all enqueued events (in FIFO order). Calling
263                            <code class="code">execute_single_queued_event()</code> will execute the oldest
264                        enqueued event.</p><p>You can query the queue size by calling <code class="code">get_message_queue_size()</code>.</p></div><div class="sect2" title="Customizing the message queues"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2691"></a><span class="command"><strong><a name="backend-queues"></a></strong></span> Customizing the message queues </h3></div></div></div><p>MSM uses by default a std::deque for its queues (one message queue for
265                        events generated during run-to-completion or with
266                        <code class="code">enqueue_event</code>, one for deferred events). Unfortunately, on some
267                        STL implementations, it is a very expensive container in size and copying
268                        time. Should this be a problem, MSM offers an alternative based on
269                        boost::circular_buffer. The policy is msm::back::queue_container_circular.
270                        To use it, you need to provide it to the back-end definition:</p><pre class="programlisting"> typedef msm::back::state_machine&lt; player_,msm::back::queue_container_circular&gt; player;           </pre><p>You can access the queues with get_message_queue and get_deferred_queue,
271                        both returning a reference or a const reference to the queues themselves.
272                        Boost::circular_buffer is outside of the scope of this documentation. What
273                        you will however need to define is the queue capacity (initially is 0) to
274                        what you think your queue will at most grow, for example (size 1 is
275                        common):</p><pre class="programlisting"> fsm.get_message_queue().set_capacity(1);           </pre></div><div class="sect2" title="Policy definition with Boost.Parameter"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2706"></a><span class="command"><strong><a name="backend-boost-parameter"></a></strong></span>Policy definition with Boost.Parameter </h3></div></div></div><p>MSM uses Boost.Parameter to allow easier definition of
276                        back::state_machine&lt;&gt; policy arguments (all except the front-end). This
277                        allows you to define policy arguments (history, compile-time / run-time,
278                        state machine analysis, container for the queues) at any position, in any
279                        number. For example: </p><pre class="programlisting"> typedef msm::back::state_machine&lt; player_,msm::back::mpl_graph_fsm_check&gt; player;
280 typedef msm::back::state_machine&lt; player_,msm::back::AlwaysHistory&gt; player;
281 typedef msm::back::state_machine&lt; player_,msm::back::mpl_graph_fsm_check,msm::back::AlwaysHistory&gt; player;
282 typedef msm::back::state_machine&lt; player_,msm::back::AlwaysHistory,msm::back::mpl_graph_fsm_check&gt; player;      </pre></div><div class="sect2" title="Choosing when to switch active states"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2714"></a><span class="command"><strong><a name="backend-state-switch"></a></strong></span>Choosing when to switch active
283                        states </h3></div></div></div><p>The UML Standard is silent about a very important question: when a
284                        transition fires, at which exact point is the target state the new active
285                        state of a state machine? At the end of the transition? After the source
286                        state has been left? What if an exception is thrown? The Standard considers
287                        that run-to-completion means a transition completes in almost no time. But
288                        even this can be in some conditions a very very long time. Consider the
289                        following example. We have a state machine representing a network
290                        connection. We can be <code class="code">Connected</code> and <code class="code">Disconnected</code>. When we move from one
291                        state to another, we send a (Boost) Signal to another entity. By default,
292                        MSM makes the target state as the new state after the transition is
293                        completed. We want to send a signal based on a flag is_connected which is
294                        true when in state Connected.</p><p>We are in state <code class="code">Disconnected</code> and receive an event <code class="code">connect</code>. The transition
295                        action will ask the state machine <code class="code">is_flag_active&lt;is_connected&gt;</code> and will
296                        get... false because we are still in <code class="code">Disconnected</code>. Hmm, what to do? We could
297                        queue the action and execute it later, but it means an extra queue, more
298                        work and higher run-time.</p><p>MSM provides the possibility (in form of a policy) for a front-end to
299                        decide when the target state becomes active. It can be:</p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>before the transition fires, if the guard will allow the
300                                    transition to fire:
301                                        <code class="code">active_state_switch_before_transition</code></p></li><li class="listitem"><p>after calling the exit action of the source state:
302                                        <code class="code">active_state_switch_after_exit</code></p></li><li class="listitem"><p>after the transition action is executed:
303                                        <code class="code">active_state_switch_after_transition_action</code></p></li><li class="listitem"><p>after the entry action of the target state is executed
304                                    (default): <code class="code">active_state_switch_after_entry</code></p></li></ul></div><p>The problem and the solution is shown for the
305                        <a class="link" href="examples/ActiveStateSetBeforeTransition.cpp" target="_top">functor-front-end</a>
306                        and <a class="link" href="examples/ActivateStateBeforeTransitionEuml.cpp" target="_top">eUML</a>. Removing <code class="code">active_state_switch_before_transition</code>
307                        will show the default state.   </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>&nbsp;</td><td width="20%" align="center"><a accesskey="u" href="ch03.html">Up</a></td><td width="40%" align="right">&nbsp;<a accesskey="n" href="ch04.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">eUML&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;Chapter&nbsp;4.&nbsp; Performance / Compilers</td></tr></table></div></body></html>