]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/msm/doc/HTML/ch03s05.html
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / msm / doc / HTML / ch03s05.html
CommitLineData
7c673cae
FG
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>