]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/statechart/doc/tutorial.html
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / statechart / doc / tutorial.html
CommitLineData
7c673cae
FG
1<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
2
3<html>
4<head>
5 <meta http-equiv="Content-Language" content="en-us">
6 <meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
7 <meta name="GENERATOR" content="Microsoft FrontPage 6.0">
8 <meta name="ProgId" content="FrontPage.Editor.Document">
9 <link rel="stylesheet" type="text/css" href="../../../boost.css">
10
11 <title>The Boost Statechart Library - Tutorial</title>
12</head>
13
14<body link="#0000FF" vlink="#800080">
15 <table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
16 "header">
17 <tr>
18 <td valign="top" width="300">
19 <h3><a href="../../../index.htm"><img alt="C++ Boost" src=
20 "../../../boost.png" border="0" width="277" height="86"></a></h3>
21 </td>
22
23 <td valign="top">
24 <h1 align="center">The Boost Statechart Library</h1>
25
26 <h2 align="center">Tutorial</h2>
27 </td>
28 </tr>
29 </table>
30 <hr>
31
32 <p>A Japanese translation of an earlier version of this tutorial can be
33 found at <a href=
34 "http://prdownloads.sourceforge.jp/jyugem/7127/fsm-tutorial-jp.pdf">http://prdownloads.sourceforge.jp/jyugem/7127/fsm-tutorial-jp.pdf</a>.
35 Kindly contributed by Mitsuo Fukasawa.</p>
36
37 <h2>Contents</h2>
38
39 <dl class="page-index">
40 <dt><a href="#Introduction">Introduction</a></dt>
41
42 <dd><a href="#HowToReadThisTutorial">How to read this tutorial</a></dd>
43
44 <dt><a href="#HelloWorld">Hello World!</a></dt>
45
46 <dt><a href="#BasicTopicsAStopWatch">Basic topics: A stop watch</a></dt>
47
48 <dd><a href="#DefiningStatesAndEvents">Defining states and
49 events</a></dd>
50
51 <dd><a href="#AddingReactions">Adding reactions</a></dd>
52
53 <dd><a href="#StateLocalStorage">State-local storage</a></dd>
54
55 <dd><a href="#GettingStateInformationOutOfTheMachine">Getting state
56 information out of the machine</a></dd>
57
58 <dt><a href="#IntermediateTopicsADigitalCamera">Intermediate topics: A
59 digital camera</a></dt>
60
61 <dd><a href=
62 "#SpreadingAStateMachineOverMultipleTranslationUnits">Spreading a state
63 machine over multiple translation units</a></dd>
64
65 <dd><a href="#DeferringEvents">Deferring events</a></dd>
66
67 <dd><a href="#Guards">Guards</a></dd>
68
69 <dd><a href="#InStateReactions">In-state reactions</a></dd>
70
71 <dd><a href="#TransitionActions">Transition actions</a></dd>
72
73 <dt><a href="#AdvancedTopics">Advanced topics</a></dt>
74
75 <dd><a href="#SpecifyingMultipleReactionsForAState">Specifying multiple
76 reactions for a state</a></dd>
77
78 <dd><a href="#PostingEvents">Posting events</a></dd>
79
80 <dd><a href="#History">History</a></dd>
81
82 <dd><a href="#OrthogonalStates">Orthogonal states</a></dd>
83
84 <dd><a href="#StateQueries">State queries</a></dd>
85
86 <dd><a href="#StateTypeInformation">State type information</a></dd>
87
88 <dd><a href="#ExceptionHandling">Exception handling</a></dd>
89
90 <dd><a href="#SubmachinesAndParameterizedStates">Submachines &amp;
91 Parametrized States</a></dd>
92
93 <dd><a href="#AsynchronousStateMachines">Asynchronous state
94 machines</a></dd>
95 </dl>
96 <hr>
97
98 <h2><a name="Introduction" id="Introduction">Introduction</a></h2>
99
100 <p>The Boost Statechart library is a framework that allows you to quickly
101 transform a UML statechart into executable C++ code, <b>without</b> needing
102 to use a code generator. Thanks to support for almost all UML features the
103 transformation is straight-forward and the resulting C++ code is a nearly
104 redundancy-free textual description of the statechart.</p>
105
106 <h3><a name="HowToReadThisTutorial" id="HowToReadThisTutorial">How to read
107 this tutorial</a></h3>
108
109 <p>This tutorial was designed to be read linearly. First time users should
110 start reading right at the beginning and stop as soon as they know enough
111 for the task at hand. Specifically:</p>
112
113 <ul>
114 <li>Small and simple machines with just a handful of states can be
115 implemented reasonably well by using the features described under
116 <a href="#BasicTopicsAStopWatch">Basic topics: A stop watch</a></li>
117
118 <li>For larger machines with up to roughly a dozen states the features
119 described under <a href="#IntermediateTopicsADigitalCamera">Intermediate
120 topics: A digital camera</a> are often helpful</li>
121
122 <li>Finally, users wanting to create even more complex machines and
123 project architects evaluating Boost.Statechart should also read the
124 <a href="#AdvancedTopics">Advanced topics</a> section at the end.
125 Moreover, reading the <a href=
126 "rationale.html#Limitations">Limitations</a> section in the Rationale is
127 strongly suggested</li>
128 </ul>
129
130 <h2><a name="HelloWorld" id="HelloWorld">Hello World!</a></h2>
131
132 <p>We will use the simplest possible program to make our first steps. The
133 statechart ...</p>
134
135 <p><img alt="HelloWorld" src="HelloWorld.gif" border="0" width="379"
136 height="94"></p>
137
138 <p>... is implemented with the following code:</p>
139 <pre>
140#include &lt;boost/statechart/state_machine.hpp&gt;
141#include &lt;boost/statechart/simple_state.hpp&gt;
142#include &lt;iostream&gt;
143
144namespace sc = boost::statechart;
145
146// We are declaring all types as <code>struct</code>s only to avoid having to
147// type <code>public</code>. If you don't mind doing so, you can just as well
148// use <code>class.</code>
149
150// We need to forward-declare the initial state because it can
151// only be defined at a point where the state machine is
152// defined.
153struct Greeting;
154
155// Boost.Statechart makes heavy use of the curiously recurring
156// template pattern. The deriving class must always be passed as
157// the first parameter to all base class templates.
158//
159// The state machine must be informed which state it has to
160// enter when the machine is initiated. That's why Greeting is
161// passed as the second template parameter.
162struct Machine : sc::state_machine&lt; Machine, Greeting &gt; {};
163
164// For each state we need to define which state machine it
165// belongs to and where it is located in the statechart. Both is
166// specified with Context argument that is passed to
167// simple_state&lt;&gt;. For a flat state machine as we have it here,
168// the context is always the state machine. Consequently,
169// Machine must be passed as the second template parameter to
170// Greeting's base (the Context parameter is explained in more
171// detail in the next example).
172struct Greeting : sc::simple_state&lt; Greeting, Machine &gt;
173{
174 // Whenever the state machine enters a state, it creates an
175 // object of the corresponding state class. The object is then
176 // kept alive as long as the machine remains in the state.
177 // Finally, the object is destroyed when the state machine
178 // exits the state. Therefore, a state entry action can be
179 // defined by adding a constructor and a state exit action can
180 // be defined by adding a destructor.
181 Greeting() { std::cout &lt;&lt; "Hello World!\n"; } // entry
182 ~Greeting() { std::cout &lt;&lt; "Bye Bye World!\n"; } // exit
183};
184
185int main()
186{
187 Machine myMachine;
188 // The machine is not yet running after construction. We start
189 // it by calling initiate(). This triggers the construction of
190 // the initial state Greeting
191 myMachine.initiate();
192 // When we leave main(), myMachine is destructed what leads to
193 // the destruction of all currently active states.
194 return 0;
195}
196</pre>
197
198 <p>This prints <code>Hello World!</code> and <code>Bye Bye World!</code>
199 before exiting.</p>
200
201 <h2><a name="BasicTopicsAStopWatch" id="BasicTopicsAStopWatch">Basic
202 topics: A stop watch</a></h2>
203
204 <p>Next we will model a simple mechanical stop watch with a state machine.
205 Such watches typically have two buttons:</p>
206
207 <ul>
208 <li>Start/Stop</li>
209
210 <li>Reset</li>
211 </ul>
212
213 <p>And two states:</p>
214
215 <ul>
216 <li>Stopped: The hands reside in the position where they were last
217 stopped:
218
219 <ul>
220 <li>Pressing the reset button moves the hands back to the 0 position.
221 The watch remains in the Stopped state</li>
222
223 <li>Pressing the start/stop button leads to a transition to the
224 Running state</li>
225 </ul>
226 </li>
227
228 <li>Running: The hands of the watch are in motion and continually show
229 the elapsed time
230
231 <ul>
232 <li>Pressing the reset button moves the hands back to the 0 position
233 and leads to a transition to the Stopped state</li>
234
235 <li>Pressing the start/stop button leads to a transition to the
236 Stopped state</li>
237 </ul>
238 </li>
239 </ul>
240
241 <p>Here is one way to specify this in UML:</p>
242
243 <p><img alt="StopWatch" src="StopWatch.gif" border="0" width="560" height=
244 "184"></p>
245
246 <h3><a name="DefiningStatesAndEvents" id="DefiningStatesAndEvents">Defining
247 states and events</a></h3>
248
249 <p>The two buttons are modeled by two events. Moreover, we also define the
250 necessary states and the initial state. <b>The following code is our
251 starting point, subsequent code snippets must be inserted</b>:</p>
252 <pre>
253#include &lt;boost/statechart/event.hpp&gt;
254#include &lt;boost/statechart/state_machine.hpp&gt;
255#include &lt;boost/statechart/simple_state.hpp&gt;
256
257namespace sc = boost::statechart;
258
259struct EvStartStop : sc::event&lt; EvStartStop &gt; {};
260struct EvReset : sc::event&lt; EvReset &gt; {};
261
262struct Active;
263struct StopWatch : sc::state_machine&lt; StopWatch, Active &gt; {};
264
265struct Stopped;
266
267// The simple_state class template accepts up to four parameters:
268// - The third parameter specifies the inner initial state, if
269// there is one. Here, only Active has inner states, which is
270// why it needs to pass its inner initial state Stopped to its
271// base
272// - The fourth parameter specifies whether and what kind of
273// history is kept
274
275// Active is the outermost state and therefore needs to pass the
276// state machine class it belongs to
277struct Active : sc::simple_state&lt;
278 Active, StopWatch, Stopped &gt; {};
279
280// Stopped and Running both specify Active as their Context,
281// which makes them nested inside Active
282struct Running : sc::simple_state&lt; Running, Active &gt; {};
283struct Stopped : sc::simple_state&lt; Stopped, Active &gt; {};
284
285// Because the context of a state must be a complete type (i.e.
286// not forward declared), a machine must be defined from
287// "outside to inside". That is, we always start with the state
288// machine, followed by outermost states, followed by the direct
289// inner states of outermost states and so on. We can do so in a
290// breadth-first or depth-first way or employ a mixture of the
291// two.
292
293int main()
294{
295 StopWatch myWatch;
296 myWatch.initiate();
297 return 0;
298}
299</pre>
300
301 <p>This compiles but doesn't do anything observable yet.</p>
302
303 <h3><a name="AddingReactions" id="AddingReactions">Adding
304 reactions</a></h3>
305
306 <p>For the moment we will use only one type of reaction: transitions. We
307 <b>insert</b> the bold parts of the following code:</p>
308 <pre>
309<b>#include &lt;boost/statechart/transition.hpp&gt;
310</b>
311// ...
312
313struct Stopped;
314struct Active : sc::simple_state&lt; Active, StopWatch, Stopped &gt;
315{
316 <b>typedef sc::transition&lt; EvReset, Active &gt; reactions;</b>
317};
318
319struct Running : sc::simple_state&lt; Running, Active &gt;
320{
321 <b>typedef sc::transition&lt; EvStartStop, Stopped &gt; reactions;</b>
322};
323
324struct Stopped : sc::simple_state&lt; Stopped, Active &gt;
325{
326 <b>typedef sc::transition&lt; EvStartStop, Running &gt; reactions;</b>
327};
328
329// A state can define an arbitrary number of reactions. That's
330// why we have to put them into an mpl::list&lt;&gt; as soon as there
331// is more than one of them
332// (see <a href=
333"#SpecifyingMultipleReactionsForAState">Specifying multiple reactions for a state</a>).
334
335int main()
336{
337 StopWatch myWatch;
338 myWatch.initiate();
339 <b>myWatch.process_event( EvStartStop() );
340</b> <b>myWatch.process_event( EvStartStop() );
341</b> <b>myWatch.process_event( EvStartStop() );
342</b> <b>myWatch.process_event( EvReset() );
343</b> return 0;
344}
345</pre>
346
347 <p>Now we have all the states and all the transitions in place and a number
348 of events are also sent to the stop watch. The machine dutifully makes the
349 transitions we would expect, but no actions are executed yet.</p>
350
351 <h3><a name="StateLocalStorage" id="StateLocalStorage">State-local
352 storage</a></h3>
353
354 <p>Next we'll make the stop watch actually measure time. Depending on the
355 state the stop watch is in, we need different variables:</p>
356
357 <ul>
358 <li>Stopped: One variable holding the elapsed time</li>
359
360 <li>Running: One variable holding the elapsed time <b>and</b> one
361 variable storing the point in time at which the watch was last
362 started.</li>
363 </ul>
364
365 <p>We observe that the elapsed time variable is needed no matter what state
366 the machine is in. Moreover, this variable should be reset to 0 when we
367 send an <code>EvReset</code> event to the machine. The other variable is
368 only needed while the machine is in the Running state. It should be set to
369 the current time of the system clock whenever we enter the Running state.
370 Upon exit we simply subtract the start time from the current system clock
371 time and add the result to the elapsed time.</p>
372 <pre>
373<b>#include &lt;ctime&gt;
374</b>
375// ...
376
377struct Stopped;
378struct Active : sc::simple_state&lt; Active, StopWatch, Stopped &gt;
379{
380 <b>public:</b>
381 typedef sc::transition&lt; EvReset, Active &gt; reactions;
382
383 <b>Active() : elapsedTime_( 0.0 ) {}
384</b> <b>double ElapsedTime() const { return elapsedTime_; }
385</b> <b>double &amp; ElapsedTime() { return elapsedTime_; }
386</b> <b>private:
387</b> <b>double elapsedTime_;
388</b>};
389
390struct Running : sc::simple_state&lt; Running, Active &gt;
391{
392 <b>public:</b>
393 typedef sc::transition&lt; EvStartStop, Stopped &gt; reactions;
394
395 <b>Running() : startTime_( std::time( 0 ) ) {}
396</b> <b>~Running()
397</b> <b>{</b>
398 // Similar to when a derived class object accesses its
399 // base class portion, context&lt;&gt;() is used to gain
400 // access to the direct or indirect context of a state.
401 // This can either be a direct or indirect outer state
402 // or the state machine itself
403 // (e.g. here: context&lt; StopWatch &gt;()).
404 <b>context&lt; Active &gt;().ElapsedTime() +=
405</b> <b>std::difftime( std::time( 0 ), startTime_ );
406</b> <b>}
407</b> <b>private:
408</b> <b>std::time_t startTime_;
409</b>};
410
411// ...
412</pre>
413
414 <p>The machine now measures the time, but we cannot yet retrieve it from
415 the main program.</p>
416
417 <p>At this point, the advantages of state-local storage (which is still a
418 relatively little-known feature) may not yet have become apparent. The FAQ
419 item "<a href="faq.html#StateLocalStorage">What's so cool about state-local
420 storage?</a>" tries to explain them in more detail by comparing this
421 StopWatch with one that does not make use of state-local storage.</p>
422
423 <h3><a name="GettingStateInformationOutOfTheMachine" id=
424 "GettingStateInformationOutOfTheMachine">Getting state information out of
425 the machine</a></h3>
426
427 <p>To retrieve the measured time, we need a mechanism to get state
428 information out of the machine. With our current machine design there are
429 two ways to do that. For the sake of simplicity we use the less efficient
430 one: <code>state_cast&lt;&gt;()</code> (StopWatch2.cpp shows the slightly
431 more complex alternative). As the name suggests, the semantics are very
432 similar to the ones of <code>dynamic_cast</code>. For example, when we call
433 <code>myWatch.state_cast&lt; const Stopped &amp; &gt;()</code> <b>and</b>
434 the machine is currently in the Stopped state, we get a reference to the
435 <code>Stopped</code> state. Otherwise <code>std::bad_cast</code> is thrown.
436 We can use this functionality to implement a <code>StopWatch</code> member
437 function that returns the elapsed time. However, rather than ask the
438 machine in which state it is and then switch to different calculations for
439 the elapsed time, we put the calculation into the Stopped and Running
440 states and use an interface to retrieve the elapsed time:</p>
441 <pre>
442<b>#include &lt;iostream&gt;
443
444</b>// ...
445
446<b>struct IElapsedTime
447{
448</b> <b>virtual double ElapsedTime() const = 0;
449};
450
451</b>struct Active;
452struct StopWatch : sc::state_machine&lt; StopWatch, Active &gt;
453{
454 <b>double ElapsedTime() const
455</b> <b>{
456</b> <b>return state_cast&lt; const IElapsedTime &amp; &gt;().ElapsedTime();
457</b> <b>}
458</b>};
459<b>
460</b>// ...
461
462struct Running : <b>IElapsedTime,</b>
463 sc::simple_state&lt; Running, Active &gt;
464{
465 public:
466 typedef sc::transition&lt; EvStartStop, Stopped &gt; reactions;
467
468 Running() : startTime_( std::time( 0 ) ) {}
469 ~Running()
470 {
471 <b>context&lt; Active &gt;().ElapsedTime() = ElapsedTime();
472</b> }
473<b>
474</b> <b>virtual double ElapsedTime() const
475</b> <b>{
476</b> <b>return context&lt; Active &gt;().ElapsedTime() +
477</b> <b>std::difftime( std::time( 0 ), startTime_ );
478</b> <b>}
479</b> private:
480 std::time_t startTime_;
481};
482
483struct Stopped : <b>IElapsedTime,</b>
484 sc::simple_state&lt; Stopped, Active &gt;
485{
486 typedef sc::transition&lt; EvStartStop, Running &gt; reactions;
487
488 <b>virtual double ElapsedTime() const
489</b> <b>{
490</b> <b>return context&lt; Active &gt;().ElapsedTime();
491</b> <b>}
492</b>};
493
494int main()
495{
496 StopWatch myWatch;
497 myWatch.initiate();
498 <b>std::cout &lt;&lt; myWatch.ElapsedTime() &lt;&lt; "\n";
499</b> myWatch.process_event( EvStartStop() );
500 <b>std::cout &lt;&lt; myWatch.ElapsedTime() &lt;&lt; "\n";
501</b> myWatch.process_event( EvStartStop() );
502 <b>std::cout &lt;&lt; myWatch.ElapsedTime() &lt;&lt; "\n";
503</b> myWatch.process_event( EvStartStop() );
504 <b>std::cout &lt;&lt; myWatch.ElapsedTime() &lt;&lt; "\n";
505</b> myWatch.process_event( EvReset() );
506 <b>std::cout &lt;&lt; myWatch.ElapsedTime() &lt;&lt; "\n";
507</b> return 0;
508}
509</pre>
510
511 <p>To actually see time being measured, you might want to single-step
512 through the statements in <code>main()</code>. The StopWatch example
513 extends this program to an interactive console application.</p>
514
515 <h2><a name="IntermediateTopicsADigitalCamera" id=
516 "IntermediateTopicsADigitalCamera">Intermediate topics: A digital
517 camera</a></h2>
518
519 <p>So far so good. However, the approach presented above has a few
520 limitations:</p>
521
522 <ul>
523 <li>Bad scalability: As soon as the compiler reaches the point where
524 <code>state_machine::initiate()</code> is called, a number of template
525 instantiations take place, which can only succeed if the full declaration
526 of each and every state of the machine is known. That is, the whole
527 layout of a state machine must be implemented in one single translation
528 unit (actions can be compiled separately, but this is of no importance
529 here). For bigger (and more real-world) state machines, this leads to the
530 following limitations:
531
532 <ul>
533 <li>At some point compilers reach their internal template
534 instantiation limits and give up. This can happen even for
535 moderately-sized machines. For example, in debug mode one popular
536 compiler refused to compile earlier versions of the BitMachine
537 example for anything above 3 bits. This means that the compiler
538 reached its limits somewhere between 8 states, 24 transitions and 16
539 states, 64 transitions</li>
540
541 <li>Multiple programmers can hardly work on the same state machine
542 simultaneously because every layout change will inevitably lead to a
543 recompilation of the whole state machine</li>
544 </ul>
545 </li>
546
547 <li>Maximum one reaction per event: According to UML a state can have
548 multiple reactions triggered by the same event. This makes sense when all
549 reactions have mutually exclusive guards. The interface we used above
550 only allows for at most one unguarded reaction for each event. Moreover,
551 the UML concepts junction and choice point are not directly
552 supported</li>
553 </ul>
554
555 <p>All these limitations can be overcome with custom reactions. <b>Warning:
556 It is easy to abuse custom reactions up to the point of invoking undefined
557 behavior. Please study the documentation before employing them!</b></p>
558
559 <h3><a name="SpreadingAStateMachineOverMultipleTranslationUnits" id=
560 "SpreadingAStateMachineOverMultipleTranslationUnits">Spreading a state
561 machine over multiple translation units</a></h3>
562
563 <p>Let's say your company would like to develop a digital camera. The
564 camera has the following controls:</p>
565
566 <ul>
567 <li>Shutter button, which can be half-pressed and fully-pressed. The
568 associated events are <code>EvShutterHalf</code>,
569 <code>EvShutterFull</code> and <code>EvShutterReleased</code></li>
570
571 <li>Config button, represented by the <code>EvConfig</code> event</li>
572
573 <li>A number of other buttons that are not of interest here</li>
574 </ul>
575
576 <p>One use case for the camera says that the photographer can half-press
577 the shutter <b>anywhere</b> in the configuration mode and the camera will
578 immediately go into shooting mode. The following statechart is one way to
579 achieve this behavior:</p>
580
581 <p><img alt="Camera" src="Camera.gif" border="0" width="544" height=
582 "317"></p>
583
584 <p>The Configuring and Shooting states will contain numerous nested states
585 while the Idle state is relatively simple. It was therefore decided to
586 build two teams. One will implement the shooting mode while the other will
587 implement the configuration mode. The two teams have already agreed on the
588 interface that the shooting team will use to retrieve the configuration
589 settings. We would like to ensure that the two teams can work with the
590 least possible interference. So, we put the two states in their own
591 translation units so that machine layout changes within the Configuring
592 state will never lead to a recompilation of the inner workings of the
593 Shooting state and vice versa.</p>
594
595 <p><b>Unlike in the previous example, the excerpts presented here often
596 outline different options to achieve the same effect. That's why the code
597 is often not equal to the Camera example code.</b> Comments mark the parts
598 where this is the case.</p>
599
600 <p>Camera.hpp:</p>
601 <pre>
602#ifndef CAMERA_HPP_INCLUDED
603#define CAMERA_HPP_INCLUDED
604
605#include &lt;boost/statechart/event.hpp&gt;
606#include &lt;boost/statechart/state_machine.hpp&gt;
607#include &lt;boost/statechart/simple_state.hpp&gt;
608#include &lt;boost/statechart/custom_reaction.hpp&gt;
609
610namespace sc = boost::statechart;
611
612struct EvShutterHalf : sc::event&lt; EvShutterHalf &gt; {};
613struct EvShutterFull : sc::event&lt; EvShutterFull &gt; {};
614struct EvShutterRelease : sc::event&lt; EvShutterRelease &gt; {};
615struct EvConfig : sc::event&lt; EvConfig &gt; {};
616
617struct NotShooting;
618struct Camera : sc::state_machine&lt; Camera, NotShooting &gt;
619{
620 bool IsMemoryAvailable() const { return true; }
621 bool IsBatteryLow() const { return false; }
622};
623
624struct Idle;
625struct NotShooting : sc::simple_state&lt;
626 NotShooting, Camera, Idle &gt;
627{
628 // With a custom reaction we only specify that we <b>might</b> do
629 // something with a particular event, but the actual reaction
630 // is defined in the react member function, which can be
631 // implemented in the .cpp file.
632 <b>typedef sc::custom_reaction&lt; EvShutterHalf &gt; reactions;</b>
633
634 // ...
635 <b>sc::result react( const EvShutterHalf &amp; );</b>
636};
637
638struct Idle : sc::simple_state&lt; Idle, NotShooting &gt;
639{
640 <b>typedef sc::custom_reaction&lt; EvConfig &gt; reactions;</b>
641
642 // ...
643 <b>sc::result react( const EvConfig &amp; );</b>
644};
645
646#endif
647</pre>
648
649 <p>Camera.cpp:</p>
650 <pre>
651#include "Camera.hpp"
652
653// The following includes are only made here but not in
654// Camera.hpp
655// The Shooting and Configuring states can themselves apply the
656// same pattern to hide their inner implementation, which
657// ensures that the two teams working on the Camera state
658// machine will never need to disturb each other.
659#include "Configuring.hpp"
660#include "Shooting.hpp"
661
662// ...
663
664// not part of the Camera example
665sc::result NotShooting::react( const EvShutterHalf &amp; )
666{
667 return transit&lt; Shooting &gt;();
668}
669
670sc::result Idle::react( const EvConfig &amp; )
671{
672 return transit&lt; Configuring &gt;();
673}
674</pre>
675
676 <p><b><font color="#FF0000">Caution: Any call to
677 <code>simple_state&lt;&gt;::transit&lt;&gt;()</code> or
678 <code>simple_state&lt;&gt;::terminate()</code> (see <a href=
679 "reference.html#transit1">reference</a>) will inevitably destruct the state
680 object (similar to <code>delete this;</code>)! That is, code executed after
681 any of these calls may invoke undefined behavior!</font></b> That's why
682 these functions should only be called as part of a return statement.</p>
683
684 <h3><a name="DeferringEvents" id="DeferringEvents">Deferring
685 events</a></h3>
686
687 <p>The inner workings of the Shooting state could look as follows:</p>
688
689 <p><img alt="Camera2" src="Camera2.gif" border="0" width="427" height=
690 "427"></p>
691
692 <p>When the user half-presses the shutter, Shooting and its inner initial
693 state Focusing are entered. In the Focusing entry action the camera
694 instructs the focusing circuit to bring the subject into focus. The
695 focusing circuit then moves the lenses accordingly and sends the EvInFocus
696 event as soon as it is done. Of course, the user can fully-press the
697 shutter while the lenses are still in motion. Without any precautions, the
698 resulting EvShutterFull event would simply be lost because the Focusing
699 state does not define a reaction for this event. As a result, the user
700 would have to fully-press the shutter again after the camera has finished
701 focusing. To prevent this, the EvShutterFull event is deferred inside the
702 Focusing state. This means that all events of this type are stored in a
703 separate queue, which is emptied into the main queue when the Focusing
704 state is exited.</p>
705 <pre>
706struct Focusing : sc::state&lt; Focusing, Shooting &gt;
707{
708 typedef mpl::list&lt;
709 sc::custom_reaction&lt; EvInFocus &gt;,
710 <b>sc::deferral&lt; EvShutterFull &gt;</b>
711 &gt; reactions;
712
713 Focusing( my_context ctx );
714 sc::result react( const EvInFocus &amp; );
715};
716</pre>
717
718 <h3><a name="Guards" id="Guards">Guards</a></h3>
719
720 <p>Both transitions originating at the Focused state are triggered by the
721 same event but they have mutually exclusive guards. Here is an appropriate
722 custom reaction:</p>
723 <pre>
724// not part of the Camera example
725sc::result Focused::react( const EvShutterFull &amp; )
726{
727 if ( context&lt; Camera &gt;().IsMemoryAvailable() )
728 {
729 return transit&lt; Storing &gt;();
730 }
731 else
732 {
733 // The following is actually a mixture between an in-state
734 // reaction and a transition. See later on how to implement
735 // proper transition actions.
736 std::cout &lt;&lt; "Cache memory full. Please wait...\n";
737 return transit&lt; Focused &gt;();
738 }
739}
740</pre>
741
742 <p>Custom reactions can of course also be implemented directly in the state
743 declaration, which is often preferable for easier browsing.</p>
744
745 <p>Next we will use a guard to prevent a transition and let outer states
746 react to the event if the battery is low:</p>
747
748 <p>Camera.cpp:</p>
749 <pre>
750// ...
751sc::result NotShooting::react( const EvShutterHalf &amp; )
752{
753 if ( context&lt; Camera &gt;().IsBatteryLow() )
754 {
755 // We cannot react to the event ourselves, so we forward it
756 // to our outer state (this is also the default if a state
757 // defines no reaction for a given event).
758 <b>return forward_event();</b>
759 }
760 else
761 {
762 return transit&lt; Shooting &gt;();
763 }
764}
765// ...
766</pre>
767
768 <h3><a name="InStateReactions" id="InStateReactions">In-state
769 reactions</a></h3>
770
771 <p>The self-transition of the Focused state could also be implemented as an
772 <a href="definitions.html#InStateReaction">in-state reaction</a>, which has
773 the same effect as long as Focused does not have any entry or exit
774 actions:</p>
775
776 <p>Shooting.cpp:</p>
777 <pre>
778// ...
779sc::result Focused::react( const EvShutterFull &amp; )
780{
781 if ( context&lt; Camera &gt;().IsMemoryAvailable() )
782 {
783 return transit&lt; Storing &gt;();
784 }
785 else
786 {
787 std::cout &lt;&lt; "Cache memory full. Please wait...\n";
788 // Indicate that the event can be discarded. So, the
789 // dispatch algorithm will stop looking for a reaction
790 // and the machine remains in the Focused state.
791 <b>return discard_event();</b>
792 }
793}
794// ...
795</pre>
796
797 <p>Because the in-state reaction is guarded, we need to employ a
798 <code>custom_reaction&lt;&gt;</code> here. For unguarded in-state reactions
799 <code><a href=
800 "reference.html#ClassTemplatein_state_reaction">in_state_reaction</a>&lt;&gt;</code>
801 should be used for better code-readability.</p>
802
803 <h3><a name="TransitionActions" id="TransitionActions">Transition
804 actions</a></h3>
805
806 <p>As an effect of every transition, actions are executed in the following
807 order:</p>
808
809 <ol>
810 <li>Starting from the innermost active state, all exit actions up to but
811 excluding the <a href="definitions.html#InnermostCommonContext">innermost
812 common context</a></li>
813
814 <li>The transition action (if present)</li>
815
816 <li>Starting from the innermost common context, all entry actions down to
817 the target state followed by the entry actions of the initial states</li>
818 </ol>
819
820 <p>Example:</p>
821
822 <p><img alt="LCA" src="LCA.gif" border="0" width="604" height="304"></p>
823
824 <p>Here the order is as follows: ~D(), ~C(), ~B(), ~A(), t(), X(), Y(),
825 Z(). The transition action t() is therefore executed in the context of the
826 InnermostCommonOuter state because the source state has already been left
827 (destructed) and the target state has not yet been entered
828 (constructed).</p>
829
830 <p>With Boost.Statechart, a transition action can be a member of <b>any</b>
831 common outer context. That is, the transition between Focusing and Focused
832 could be implemented as follows:</p>
833
834 <p>Shooting.hpp:</p>
835 <pre>
836// ...
837struct Focusing;
838struct Shooting : sc::simple_state&lt; Shooting, Camera, Focusing &gt;
839{
840 typedef sc::transition&lt;
841 EvShutterRelease, NotShooting &gt; reactions;
842
843 // ...
844 <b>void DisplayFocused( const EvInFocus &amp; );</b>
845};
846
847// ...
848
849// not part of the Camera example
850struct Focusing : sc::simple_state&lt; Focusing, Shooting &gt;
851{
852 typedef sc::transition&lt; EvInFocus, Focused<b>,</b>
853 <b>Shooting, &amp;Shooting::DisplayFocused</b> &gt; reactions;
854};
855</pre>
856
857 <p><b>Or</b>, the following is also possible (here the state machine itself
858 serves as the outermost context):</p>
859 <pre>
860// not part of the Camera example
861struct Camera : sc::state_machine&lt; Camera, NotShooting &gt;
862{
863 <b>void DisplayFocused( const EvInFocus &amp; );</b>
864};
865</pre>
866 <pre>
867// not part of the Camera example
868struct Focusing : sc::simple_state&lt; Focusing, Shooting &gt;
869{
870 typedef sc::transition&lt; EvInFocus, Focused<b>,</b>
871 <b>Camera, &amp;Camera::DisplayFocused</b> &gt; reactions;
872};
873</pre>
874
875 <p>Naturally, transition actions can also be invoked from custom
876 reactions:</p>
877
878 <p>Shooting.cpp:</p>
879 <pre>
880// ...
881sc::result Focusing::react( const EvInFocus &amp; evt )
882{
883 // We have to manually forward evt
884 return transit&lt; Focused &gt;( <b>&amp;Shooting::DisplayFocused</b>, evt );
885}
886</pre>
887
888 <h2><a name="AdvancedTopics" id="AdvancedTopics">Advanced topics</a></h2>
889
890 <h3><a name="SpecifyingMultipleReactionsForAState" id=
891 "SpecifyingMultipleReactionsForAState">Specifying multiple reactions for a
892 state</a></h3>
893
894 <p>Often a state must define reactions for more than one event. In this
895 case, an <code>mpl::list&lt;&gt;</code> must be used as outlined below:</p>
896 <pre>
897// ...
898
899<b>#include &lt;boost/mpl/list.hpp&gt;
900</b>
901<b>namespace mpl = boost::mpl;
902</b>
903// ...
904
905struct Playing : sc::simple_state&lt; Playing, Mp3Player &gt;
906{
907 typdef <b>mpl::list&lt;</b>
908 sc::custom_reaction&lt; EvFastForward &gt;,
909 sc::transition&lt; EvStop, Stopped &gt; <b>&gt;</b> reactions;
910
911 /* ... */
912};
913</pre>
914
915 <h3><a name="PostingEvents" id="PostingEvents">Posting events</a></h3>
916
917 <p>Non-trivial state machines often need to post internal events. Here's an
918 example of how to do this:</p>
919 <pre>
920Pumping::~Pumping()
921{
922 post_event( EvPumpingFinished() );
923}
924</pre>
925
926 <p>The event is pushed into the main queue. The events in the queue are
927 processed as soon as the current reaction is completed. Events can be
928 posted from inside <code>react</code> functions, entry-, exit- and
929 transition actions. However, posting from inside entry actions is a bit
930 more complicated (see e.g. <code>Focusing::Focusing()</code> in
931 <code>Shooting.cpp</code> in the Camera example):</p>
932 <pre>
933struct Pumping : <b>sc::state</b>&lt; Pumping, Purifier &gt;
934{
935 <b>Pumping( my_context ctx ) : my_base( ctx )</b>
936 {
937 post_event( EvPumpingStarted() );
938 }
939 // ...
940};
941</pre>
942
943 <p>As soon as an entry action of a state needs to contact the "outside
944 world" (here: the event queue in the state machine), the state must derive
945 from <code>state&lt;&gt;</code> rather than from
946 <code>simple_state&lt;&gt;</code> and must implement a forwarding
947 constructor as outlined above (apart from the constructor,
948 <code>state&lt;&gt;</code> offers the same interface as
949 <code>simple_state&lt;&gt;</code>). Hence, this must be done whenever an
950 entry action makes one or more calls to the following functions:</p>
951
952 <ul>
953 <li><code>simple_state&lt;&gt;::post_event()</code></li>
954
955 <li>
956 <code>simple_state&lt;&gt;::clear_shallow_history&lt;&gt;()</code></li>
957
958 <li><code>simple_state&lt;&gt;::clear_deep_history&lt;&gt;()</code></li>
959
960 <li><code>simple_state&lt;&gt;::outermost_context()</code></li>
961
962 <li><code>simple_state&lt;&gt;::context&lt;&gt;()</code></li>
963
964 <li><code>simple_state&lt;&gt;::state_cast&lt;&gt;()</code></li>
965
966 <li><code>simple_state&lt;&gt;::state_downcast&lt;&gt;()</code></li>
967
968 <li><code>simple_state&lt;&gt;::state_begin()</code></li>
969
970 <li><code>simple_state&lt;&gt;::state_end()</code></li>
971 </ul>
972
973 <p>In my experience, these functions are needed only rarely in entry
974 actions so this workaround should not uglify user code too much.</p>
975
976 <h3><a name="History" id="History">History</a></h3>
977
978 <p>Photographers testing beta versions of our <a href=
979 "#SpreadingAStateMachineOverMultipleTranslationUnits">digital camera</a>
980 said that they really liked that half-pressing the shutter anytime (even
981 while the camera is being configured) immediately readies the camera for
982 picture-taking. However, most of them found it unintuitive that the camera
983 always goes into the idle mode after releasing the shutter. They would
984 rather see the camera go back into the state it had before half-pressing
985 the shutter. This way they can easily test the influence of a configuration
986 setting by modifying it, half- and then fully-pressing the shutter to take
987 a picture. Finally, releasing the shutter will bring them back to the
988 screen where they have modified the setting. To implement this behavior
989 we'd change the state chart as follows:</p>
990
991 <p><img alt="CameraWithHistory1" src="CameraWithHistory1.gif" border="0"
992 width="542" height="378"></p>
993
994 <p>As mentioned earlier, the Configuring state contains a fairly complex
995 and deeply nested inner machine. Naturally, we'd like to restore the
996 previous state down to the <a href=
997 "definitions.html#InnermostState">innermost state</a>(s) in Configuring,
998 that's why we use a deep history pseudo state. The associated code looks as
999 follows:</p>
1000 <pre>
1001// not part of the Camera example
1002struct NotShooting : sc::simple_state&lt;
1003 NotShooting, Camera, Idle, <b>sc::has_deep_history</b> &gt;
1004{
1005 // ...
1006};
1007
1008// ...
1009
1010struct Shooting : sc::simple_state&lt; Shooting, Camera, Focusing &gt;
1011{
1012 typedef sc::transition&lt;
1013 EvShutterRelease, <b>sc::deep_history&lt; Idle &gt;</b> &gt; reactions;
1014
1015 // ...
1016};
1017</pre>
1018
1019 <p>History has two phases: Firstly, when the state containing the history
1020 pseudo state is exited, information about the previously active inner state
1021 hierarchy must be saved. Secondly, when a transition to the history pseudo
1022 state is made later, the saved state hierarchy information must be
1023 retrieved and the appropriate states entered. The former is expressed by
1024 passing either <code>has_shallow_history</code>,
1025 <code>has_deep_history</code> or <code>has_full_history</code> (which
1026 combines shallow and deep history) as the last parameter to the
1027 <code>simple_state</code> and <code>state</code> class templates. The
1028 latter is expressed by specifying either
1029 <code>shallow_history&lt;&gt;</code> or <code>deep_history&lt;&gt;</code>
1030 as a transition destination or, as we'll see in an instant, as an inner
1031 initial state. Because it is possible that a state containing a history
1032 pseudo state has never been entered before a transition to history is made,
1033 both class templates demand a parameter specifying the default state to
1034 enter in such situations.</p>
1035
1036 <p>The redundancy necessary for using history is checked for consistency at
1037 compile time. That is, the state machine wouldn't have compiled had we
1038 forgotten to pass <code>has_deep_history</code> to the base of
1039 <code>NotShooting</code>.</p>
1040
1041 <p>Another change request filed by a few beta testers says that they would
1042 like to see the camera go back into the state it had before turning it off
1043 when they turn it back on. Here's the implementation:</p>
1044
1045 <p><img alt="CameraWithHistory2" src="CameraWithHistory2.gif" border="0"
1046 width="468" height="483"></p>
1047 <pre>
1048// ...
1049
1050// not part of the Camera example
1051struct NotShooting : sc::simple_state&lt; NotShooting, Camera,
1052 <b>mpl::list&lt; sc::deep_history&lt; Idle &gt; &gt;</b>,
1053 <b>sc::has_deep_history</b> &gt;
1054{
1055 // ...
1056};
1057
1058// ...
1059</pre>
1060
1061 <p>Unfortunately, there is a small inconvenience due to some
1062 template-related implementation details. When the inner initial state is a
1063 class template instantiation we always have to put it into an
1064 <code>mpl::list&lt;&gt;</code>, although there is only one inner initial
1065 state. Moreover, the current deep history implementation has some <a href=
1066 "rationale.html#Limitations">limitations</a>.</p>
1067
1068 <h3><a name="OrthogonalStates" id="OrthogonalStates">Orthogonal
1069 states</a></h3>
1070
1071 <p><img alt="OrthogonalStates" src="OrthogonalStates.gif" border="0" width=
1072 "633" height="393"></p>
1073
1074 <p>To implement this statechart you simply specify more than one inner
1075 initial state (see the Keyboard example):</p>
1076 <pre>
1077struct Active;
1078struct Keyboard : sc::state_machine&lt; Keyboard, Active &gt; {};
1079
1080struct NumLockOff;
1081struct CapsLockOff;
1082struct ScrollLockOff;
1083struct Active: sc::simple_state&lt; Active, Keyboard,
1084 <b>mpl::list&lt; NumLockOff, CapsLockOff, ScrollLockOff &gt;</b> &gt; {};
1085</pre>
1086
1087 <p>Active's inner states must declare which orthogonal region they belong
1088 to:</p>
1089 <pre>
1090struct EvNumLockPressed : sc::event&lt; EvNumLockPressed &gt; {};
1091struct EvCapsLockPressed : sc::event&lt; EvCapsLockPressed &gt; {};
1092struct EvScrollLockPressed :
1093 sc::event&lt; EvScrollLockPressed &gt; {};
1094
1095struct NumLockOn : sc::simple_state&lt;
1096 NumLockOn, Active<b>::orthogonal&lt; 0 &gt;</b> &gt;
1097{
1098 typedef sc::transition&lt;
1099 EvNumLockPressed, NumLockOff &gt; reactions;
1100};
1101
1102struct NumLockOff : sc::simple_state&lt;
1103 NumLockOff, Active<b>::orthogonal&lt; 0 &gt;</b> &gt;
1104{
1105 typedef sc::transition&lt;
1106 EvNumLockPressed, NumLockOn &gt; reactions;
1107};
1108
1109struct CapsLockOn : sc::simple_state&lt;
1110 CapsLockOn, Active<b>::orthogonal&lt; 1 &gt;</b> &gt;
1111{
1112 typedef sc::transition&lt;
1113 EvCapsLockPressed, CapsLockOff &gt; reactions;
1114};
1115
1116struct CapsLockOff : sc::simple_state&lt;
1117 CapsLockOff, Active<b>::orthogonal&lt; 1 &gt;</b> &gt;
1118{
1119 typedef sc::transition&lt;
1120 EvCapsLockPressed, CapsLockOn &gt; reactions;
1121};
1122
1123struct ScrollLockOn : sc::simple_state&lt;
1124 ScrollLockOn, Active<b>::orthogonal&lt; 2 &gt;</b> &gt;
1125{
1126 typedef sc::transition&lt;
1127 EvScrollLockPressed, ScrollLockOff &gt; reactions;
1128};
1129
1130struct ScrollLockOff : sc::simple_state&lt;
1131 ScrollLockOff, Active<b>::orthogonal&lt; 2 &gt;</b> &gt;
1132{
1133 typedef sc::transition&lt;
1134 EvScrollLockPressed, ScrollLockOn &gt; reactions;
1135};
1136</pre>
1137
1138 <p><code>orthogonal&lt; 0 &gt;</code> is the default, so
1139 <code>NumLockOn</code> and <code>NumLockOff</code> could just as well pass
1140 <code>Active</code> instead of <code>Active::orthogonal&lt; 0 &gt;</code>
1141 to specify their context. The numbers passed to the <code>orthogonal</code>
1142 member template must correspond to the list position in the outer state.
1143 Moreover, the orthogonal position of the source state of a transition must
1144 correspond to the orthogonal position of the target state. Any violations
1145 of these rules lead to compile time errors. Examples:</p>
1146 <pre>
1147// Example 1: does not compile because Active specifies
1148// only 3 orthogonal regions
1149struct WhateverLockOn: sc::simple_state&lt;
1150 WhateverLockOn, Active<b>::</b>orthogonal&lt; <b>3</b> &gt; &gt; {};
1151
1152// Example 2: does not compile because Active specifies
1153// that NumLockOff is part of the "0th" orthogonal region
1154struct NumLockOff : sc::simple_state&lt;
1155 NumLockOff, Active<b>::</b>orthogonal&lt; <b>1</b> &gt; &gt; {};
1156
1157// Example 3: does not compile because a transition between
1158// different orthogonal regions is not permitted
1159struct CapsLockOn : sc::simple_state&lt;
1160 CapsLockOn, Active<b>::</b>orthogonal&lt; <b>1</b> &gt; &gt;
1161{
1162 typedef sc::transition&lt;
1163 EvCapsLockPressed, CapsLockOff &gt; reactions;
1164};
1165
1166struct CapsLockOff : sc::simple_state&lt;
1167 CapsLockOff, Active<b>::</b>orthogonal&lt; <b>2</b> &gt; &gt;
1168{
1169 typedef sc::transition&lt;
1170 EvCapsLockPressed, CapsLockOn &gt; reactions;
1171};
1172</pre>
1173
1174 <h3><a name="StateQueries" id="StateQueries">State queries</a></h3>
1175
1176 <p>Often reactions in a state machine depend on the active state in one or
1177 more orthogonal regions. This is because orthogonal regions are not
1178 completely orthogonal or a certain reaction in an outer state can only take
1179 place if the inner orthogonal regions are in particular states. For this
1180 purpose, the <code>state_cast&lt;&gt;</code> function introduced under
1181 <a href="#GettingStateInformationOutOfTheMachine">Getting state information
1182 out of the machine</a> is also available within states.</p>
1183
1184 <p>As a somewhat far-fetched example, let's assume that our <a href=
1185 "#OrthogonalStates">keyboard</a> also accepts
1186 <code>EvRequestShutdown</code> events, the reception of which makes the
1187 keyboard terminate only if all lock keys are in the off state. We would
1188 then modify the Keyboard state machine as follows:</p>
1189 <pre>
1190struct EvRequestShutdown : sc::event&lt; EvRequestShutdown &gt; {};
1191
1192struct NumLockOff;
1193struct CapsLockOff;
1194struct ScrollLockOff;
1195struct Active: sc::simple_state&lt; Active, Keyboard,
1196 mpl::list&lt; NumLockOff, CapsLockOff, ScrollLockOff &gt; &gt;
1197{
1198 typedef sc::custom_reaction&lt; EvRequestShutdown &gt; reactions;
1199
1200 sc::result react( const EvRequestShutdown &amp; )
1201 {
1202 if ( ( state_downcast&lt; const NumLockOff * &gt;() != 0 ) &amp;&amp;
1203 ( state_downcast&lt; const CapsLockOff * &gt;() != 0 ) &amp;&amp;
1204 ( state_downcast&lt; const ScrollLockOff * &gt;() != 0 ) )
1205 {
1206 return terminate();
1207 }
1208 else
1209 {
1210 return discard_event();
1211 }
1212 }
1213};
1214</pre>
1215
1216 <p>Passing a pointer type instead of reference type results in 0 pointers
1217 being returned instead of <code>std::bad_cast</code> being thrown when the
1218 cast fails. Note also the use of <code>state_downcast&lt;&gt;()</code>
1219 instead of <code>state_cast&lt;&gt;()</code>. Similar to the differences
1220 between <code>boost::polymorphic_downcast&lt;&gt;()</code> and
1221 <code>dynamic_cast</code>, <code>state_downcast&lt;&gt;()</code> is a much
1222 faster variant of <code>state_cast&lt;&gt;()</code> and can only be used
1223 when the passed type is a most-derived type.
1224 <code>state_cast&lt;&gt;()</code> should only be used if you want to query
1225 an additional base.</p>
1226
1227 <h4>Custom state queries</h4>
1228
1229 <p>It is often desirable to find out exactly which state(s) a machine
1230 currently resides in. To some extent this is already possible with
1231 <code>state_cast&lt;&gt;()</code> and <code>state_downcast&lt;&gt;()</code>
1232 but their utility is rather limited because both only return a yes/no
1233 answer to the question "Are you in state X?". It is possible to ask more
1234 sophisticated questions when you pass an additional base class rather than
1235 a state class to <code>state_cast&lt;&gt;()</code> but this involves more
1236 work (all states need to derive from and implement the additional base), is
1237 slow (under the hood <code>state_cast&lt;&gt;()</code> uses
1238 <code>dynamic_cast</code>), forces projects to compile with C++ RTTI turned
1239 on and has a negative impact on state entry/exit speed.</p>
1240
1241 <p>Especially for debugging it would be so much more useful being able to
1242 ask "In which state(s) are you?". For this purpose it is possible to
1243 iterate over all active <b>innermost</b> states with
1244 <code>state_machine&lt;&gt;::state_begin()</code> and
1245 <code>state_machine&lt;&gt;::state_end()</code>. Dereferencing the returned
1246 iterator returns a reference to <code>const
1247 state_machine&lt;&gt;::state_base_type</code>, the common base of all
1248 states. We can thus print the currently active state configuration as
1249 follows (see the Keyboard example for the complete code):</p>
1250 <pre>
1251void DisplayStateConfiguration( const Keyboard &amp; kbd )
1252{
1253 char region = 'a';
1254
1255 for (
1256 Keyboard::state_iterator pLeafState = kbd.state_begin();
1257 pLeafState != kbd.state_end(); ++pLeafState )
1258 {
1259 std::cout &lt;&lt; "Orthogonal region " &lt;&lt; region &lt;&lt; ": ";
1260 // The following use of typeid assumes that
1261 // BOOST_STATECHART_USE_NATIVE_RTTI is defined
1262 std::cout &lt;&lt; typeid( *pLeafState ).name() &lt;&lt; "\n";
1263 ++region;
1264 }
1265}
1266</pre>
1267
1268 <p>If necessary, the outer states can be accessed with
1269 <code>state_machine&lt;&gt;::state_base_type::outer_state_ptr()</code>,
1270 which returns a pointer to <code>const
1271 state_machine&lt;&gt;::state_base_type</code>. When called on an outermost
1272 state this function simply returns 0.</p>
1273
1274 <h3><a name="StateTypeInformation" id="StateTypeInformation">State type
1275 information</a></h3>
1276
1277 <p>To cut down on executable size some applications must be compiled with
1278 C++ RTTI turned off. This would render the ability to iterate over all
1279 active states pretty much useless if it weren't for the following two
1280 functions:</p>
1281
1282 <ul>
1283 <li><code>static <i>unspecified_type</i>
1284 simple_state&lt;&gt;::static_type()</code></li>
1285
1286 <li><code><i>unspecified_type<br></i> &nbsp;
1287 state_machine&lt;&gt;::state_base_type::dynamic_type() const</code></li>
1288 </ul>
1289
1290 <p>Both return a value that is comparable via <code>operator==()</code> and
1291 <code>std::less&lt;&gt;</code>. This alone would be enough to implement the
1292 <code>DisplayStateConfiguration</code> function above without the help of
1293 <code>typeid</code> but it is still somewhat cumbersome as a map must be
1294 used to associate the type information values with the state names.</p>
1295
1296 <h4><a name="CustomStateTypeInformation" id=
1297 "CustomStateTypeInformation">Custom state type information</a></h4>
1298
1299 <p>That's why the following functions are also provided (only available
1300 when <a href=
1301 "configuration.html#ApplicationDefinedMacros">BOOST_STATECHART_USE_NATIVE_RTTI</a>
1302 is <b>not</b> defined):</p>
1303
1304 <ul>
1305 <li><code>template&lt; class T &gt;<br>
1306 static void simple_state&lt;&gt;::custom_static_type_ptr( const T *
1307 );</code></li>
1308
1309 <li><code>template&lt; class T &gt;<br>
1310 static const T *
1311 simple_state&lt;&gt;::custom_static_type_ptr();</code></li>
1312
1313 <li><code>template&lt; class T &gt;<br>
1314 const T * state_machine&lt;&gt;::<br>
1315 &nbsp; state_base_type::custom_dynamic_type_ptr() const;</code></li>
1316 </ul>
1317
1318 <p>These allow us to directly associate arbitrary state type information
1319 with each state ...</p>
1320 <pre>
1321// ...
1322
1323int main()
1324{
1325 NumLockOn::custom_static_type_ptr( "NumLockOn" );
1326 NumLockOff::custom_static_type_ptr( "NumLockOff" );
1327 CapsLockOn::custom_static_type_ptr( "CapsLockOn" );
1328 CapsLockOff::custom_static_type_ptr( "CapsLockOff" );
1329 ScrollLockOn::custom_static_type_ptr( "ScrollLockOn" );
1330 ScrollLockOff::custom_static_type_ptr( "ScrollLockOff" );
1331
1332 // ...
1333}
1334</pre>
1335
1336 <p>... and rewrite the display function as follows:</p>
1337 <pre>
1338void DisplayStateConfiguration( const Keyboard &amp; kbd )
1339{
1340 char region = 'a';
1341
1342 for (
1343 Keyboard::state_iterator pLeafState = kbd.state_begin();
1344 pLeafState != kbd.state_end(); ++pLeafState )
1345 {
1346 std::cout &lt;&lt; "Orthogonal region " &lt;&lt; region &lt;&lt; ": ";
1347 std::cout &lt;&lt;
1348 pLeafState-&gt;custom_dynamic_type_ptr&lt; char &gt;() &lt;&lt; "\n";
1349 ++region;
1350 }
1351}
1352</pre>
1353
1354 <h3><a name="ExceptionHandling" id="ExceptionHandling">Exception
1355 handling</a></h3>
1356
1357 <p>Exceptions can be propagated from all user code except from state
1358 destructors. Out of the box, the state machine framework is configured for
1359 simple exception handling and does not catch any of these exceptions, so
1360 they are immediately propagated to the state machine client. A scope guard
1361 inside the <code>state_machine&lt;&gt;</code> ensures that all state
1362 objects are destructed before the exception is caught by the client. The
1363 scope guard does not attempt to call any <code>exit</code> functions (see
1364 <a href="#TwoStageExit">Two stage exit</a> below) that states might define
1365 as these could themselves throw other exceptions which would mask the
1366 original exception. Consequently, if a state machine should do something
1367 more sensible when exceptions are thrown, it has to catch them before they
1368 are propagated into the Boost.Statechart framework. This exception handling
1369 scheme is often appropriate but it can lead to considerable code
1370 duplication in state machines where many actions can trigger exceptions
1371 that need to be handled inside the state machine (see <a href=
1372 "rationale.html#ErrorHandling">Error handling</a> in the Rationale).<br>
1373 That's why exception handling can be customized through the
1374 <code>ExceptionTranslator</code> parameter of the
1375 <code>state_machine</code> class template. Since the out-of-the box
1376 behavior is to <b>not</b> translate any exceptions, the default argument
1377 for this parameter is <code>null_exception_translator</code>. A
1378 <code>state_machine&lt;&gt;</code> subtype can be configured for advanced
1379 exception handling by specifying the library-supplied
1380 <code>exception_translator&lt;&gt;</code> instead. This way, the following
1381 happens when an exception is propagated from user code:</p>
1382
1383 <ol>
1384 <li>The exception is caught inside the framework</li>
1385
1386 <li>In the catch block, an <code>exception_thrown</code> event is
1387 allocated on the stack</li>
1388
1389 <li>Also in the catch block, an <b>immediate</b> dispatch of the
1390 <code>exception_thrown</code> event is attempted. That is, possibly
1391 remaining events in the queue are dispatched only after the exception has
1392 been handled successfully</li>
1393
1394 <li>If the exception was handled successfully, the state machine returns
1395 to the client normally. If the exception could not be handled
1396 successfully, the original exception is rethrown so that the client of
1397 the state machine can handle the exception</li>
1398 </ol>
1399
1400 <p>On platforms with buggy exception handling implementations users would
1401 probably want to implement their own model of the <a href=
1402 "reference.html#ExceptionTranslator">ExceptionTranslator concept</a> (see
1403 also <a href="#DiscriminatingExceptions">Discriminating
1404 exceptions</a>).</p>
1405
1406 <h4>Successful exception handling</h4>
1407
1408 <p>An exception is considered handled successfully, if:</p>
1409
1410 <ul>
1411 <li>an appropriate reaction for the <code>exception_thrown</code> event
1412 has been found, <b>and</b></li>
1413
1414 <li>the state machine is in a stable state after the reaction has
1415 completed.</li>
1416 </ul>
1417
1418 <p>The second condition is important for scenarios 2 and 3 in the next
1419 section. In these scenarios, the state machine is in the middle of a
1420 transition when the exception is handled. The machine would be left in an
1421 invalid state, should the reaction simply discard the event without doing
1422 anything else. <code>exception_translator&lt;&gt;</code> simply rethrows
1423 the original exception if the exception handling was unsuccessful. Just as
1424 with simple exception handling, in this case a scope guard inside the
1425 <code>state_machine&lt;&gt;</code> ensures that all state objects are
1426 destructed before the exception is caught by the client.</p>
1427
1428 <h4>Which states can react to an <code>exception_thrown</code> event?</h4>
1429
1430 <p>Short answer: If the state machine is stable when the exception is
1431 thrown, the state that caused the exception is first tried for a reaction.
1432 Otherwise the outermost <a href="definitions.html#UnstableState">unstable
1433 state</a> is first tried for a reaction.</p>
1434
1435 <p>Longer answer: There are three scenarios:</p>
1436
1437 <ol>
1438 <li>A <code>react</code> member function propagates an exception
1439 <b>before</b> calling any of the reaction functions or the action
1440 executed during an in-state reaction propagates an exception. The state
1441 that caused the exception is first tried for a reaction, so the following
1442 machine will transit to Defective after receiving an EvStart event:<br>
1443 <br>
1444 <img alt="ThrowingInStateReaction" src="ThrowingInStateReaction.gif"
1445 border="0" width="362" height="182"><br>
1446 <br></li>
1447
1448 <li>A state entry action (constructor) propagates an exception:<br>
1449
1450 <ul>
1451 <li>If there are no orthogonal regions, the direct outer state of the
1452 state that caused the exception is first tried for a reaction, so the
1453 following machine will transit to Defective after trying to enter
1454 Stopped:<br>
1455 <br>
1456 <img alt="ThrowingEntryAction" src="ThrowingEntryAction.gif" border=
1457 "0" width="438" height="241"><br></li>
1458
1459 <li>If there are orthogonal regions, the outermost <a href=
1460 "definitions.html#UnstableState">unstable state</a> is first tried
1461 for a reaction. The outermost unstable state is found by first
1462 selecting the direct outer state of the state that caused the
1463 exception and then moving outward until a state is found that is
1464 unstable but has no direct or indirect outer states that are
1465 unstable. This more complex rule is necessary because only reactions
1466 associated with the outermost unstable state (or any of its direct or
1467 indirect outer states) are able to bring the machine back into a
1468 stable state. Consider the following statechart:<br>
1469 <br>
1470 <img alt="OutermostUnstableState" src="OutermostUnstableState.gif"
1471 border="0" width="467" height="572"><br>
1472 <br>
1473 Whether this state machine will ultimately transition to E or F after
1474 initiation depends on which of the two orthogonal regions is
1475 initiated first. If the upper orthogonal region is initiated first,
1476 the entry sequence is as follows: A, D, B, (exception is thrown).
1477 Both D and B were successfully entered, so B is the outermost
1478 unstable state when the exception is thrown and the machine will
1479 therefore transition to F. However, if the lower orthogonal region is
1480 initiated first, the sequence is as follows: A, B, (exception is
1481 thrown). D was never entered so A is the outermost unstable state
1482 when the exception is thrown and the machine will therefore
1483 transition to E.<br>
1484 In practice these differences rarely matter as top-level error
1485 recovery is adequate for most state machines. However, since the
1486 sequence of initiation is clearly defined (orthogonal region 0 is
1487 always initiated first, then region 1 and so forth), users <b>can</b>
1488 accurately control when and where they want to handle
1489 exceptions<br></li>
1490 </ul>
1491 </li>
1492
1493 <li>A transition action propagates an exception: The innermost common
1494 outer state of the source and the target state is first tried for a
1495 reaction, so the following machine will transit to Defective after
1496 receiving an EvStartStop event:<br>
1497 <br>
1498 <img alt="ThrowingTransitionAction" src="ThrowingTransitionAction.gif"
1499 border="0" width="422" height="362"></li>
1500 </ol>
1501
1502 <p>As with a normal event, the dispatch algorithm will move outward to find
1503 a reaction if the first tried state does not provide one (or if the
1504 reaction explicitly returned <code>forward_event();</code>). However, <b>in
1505 contrast to normal events, it will give up once it has unsuccessfully tried
1506 an outermost state</b>, so the following machine will <b>not</b> transit to
1507 Defective after receiving an EvNumLockPressed event:</p>
1508
1509 <p><img alt="ExceptionsAndOrthStates" src="ExceptionsAndOrthStates.gif"
1510 border="0" width="571" height="331"></p>
1511
1512 <p>Instead, the machine is terminated and the original exception
1513 rethrown.</p>
1514
1515 <h4><a name="DiscriminatingExceptions" id=
1516 "DiscriminatingExceptions">Discriminating exceptions</a></h4>
1517
1518 <p>Because the <code>exception_thrown</code> event is dispatched from
1519 within the catch block, we can rethrow and catch the exception in a custom
1520 reaction:</p>
1521 <pre>
1522struct Defective : sc::simple_state&lt;
1523 Defective, Purifier &gt; {};
1524
1525// Pretend this is a state deeply nested in the Purifier
1526// state machine
1527struct Idle : sc::simple_state&lt; Idle, Purifier &gt;
1528{
1529 typedef mpl::list&lt;
1530 sc::custom_reaction&lt; EvStart &gt;,
1531 sc::custom_reaction&lt; sc::exception_thrown &gt;
1532 &gt; reactions;
1533
1534 sc::result react( const EvStart &amp; )
1535 {
1536 throw std::runtime_error( "" );
1537 }
1538
1539 sc::result react( const sc::exception_thrown &amp; )
1540 {
1541 try
1542 {
1543 <b>throw;</b>
1544 }
1545 catch ( const std::runtime_error &amp; )
1546 {
1547 // only std::runtime_errors will lead to a transition
1548 // to Defective ...
1549 return transit&lt; Defective &gt;();
1550 }
1551 catch ( ... )
1552 {
1553 // ... all other exceptions are forwarded to our outer
1554 // state(s). The state machine is terminated and the
1555 // exception rethrown if the outer state(s) can't
1556 // handle it either...
1557 return forward_event();
1558 }
1559
1560 // Alternatively, if we want to terminate the machine
1561 // immediately, we can also either rethrow or throw
1562 // a different exception.
1563 }
1564};
1565</pre>
1566
1567 <p><b>Unfortunately, this idiom (using <code>throw;</code> inside a
1568 <code>try</code> block nested inside a <code>catch</code> block) does not
1569 work on at least one very popular compiler.</b> If you have to use one of
1570 these platforms, you can pass a customized exception translator class to
1571 the <code>state_machine</code> class template. This will allow you to
1572 generate different events depending on the type of the exception.</p>
1573
1574 <h4><a name="TwoStageExit" id="TwoStageExit">Two stage exit</a></h4>
1575
1576 <p>If a <code>simple_state&lt;&gt;</code> or <code>state&lt;&gt;</code>
1577 subtype declares a public member function with the signature <code>void
1578 exit()</code> then this function is called just before the state object is
1579 destructed. As explained under <a href="rationale.html#ErrorHandling">Error
1580 handling</a> in the Rationale, this is useful for two things that would
1581 otherwise be difficult or cumbersome to achieve with destructors only:</p>
1582
1583 <ol>
1584 <li>To signal a failure in an exit action</li>
1585
1586 <li>To execute certain exit actions <b>only</b> during a transition or a
1587 termination but not when the state machine object is destructed</li>
1588 </ol>
1589
1590 <p>A few points to consider before employing <code>exit()</code>:</p>
1591
1592 <ul>
1593 <li>There is no guarantee that <code>exit()</code> will be called:
1594
1595 <ul>
1596 <li>If the client destructs the state machine object without calling
1597 <code>terminate()</code> beforehand then the currently active states
1598 are destructed without calling <code>exit()</code>. This is necessary
1599 because an exception that is possibly thrown from <code>exit()</code>
1600 could not be propagated on to the state machine client</li>
1601
1602 <li><code>exit()</code> is not called when a previously executed
1603 action propagated an exception and that exception has not (yet) been
1604 handled successfully. This is because a new exception that could
1605 possibly be thrown from <code>exit()</code> would mask the original
1606 exception</li>
1607 </ul>
1608 </li>
1609
1610 <li>A state is considered exited, even if its <code>exit</code> function
1611 propagated an exception. That is, the state object is inevitably
1612 destructed right after calling <code>exit()</code>, regardless of whether
1613 <code>exit()</code> propagated an exception or not. A state machine
1614 configured for advanced exception handling is therefore always unstable
1615 while handling an exception propagated from an <code>exit</code>
1616 function</li>
1617
1618 <li>In a state machine configured for advanced exception handling the
1619 processing rules for an exception event resulting from an exception
1620 propagated from <code>exit()</code> are analogous to the ones defined for
1621 exceptions propagated from state constructors. That is, the outermost
1622 unstable state is first tried for a reaction and the dispatcher then
1623 moves outward until an appropriate reaction is found</li>
1624 </ul>
1625
1626 <h3><a name="SubmachinesAndParameterizedStates" id=
1627 "SubmachinesAndParameterizedStates">Submachines &amp; parameterized
1628 states</a></h3>
1629
1630 <p>Submachines are to event-driven programming what functions are to
1631 procedural programming, reusable building blocks implementing often needed
1632 functionality. The associated UML notation is not entirely clear to me. It
1633 seems to be severely limited (e.g. the same submachine cannot appear in
1634 different orthogonal regions) and does not seem to account for obvious
1635 stuff like e.g. parameters.</p>
1636
1637 <p>Boost.Statechart is completely unaware of submachines but they can be
1638 implemented quite nicely with templates. Here, a submachine is used to
1639 improve the copy-paste implementation of the keyboard machine discussed
1640 under <a href="#OrthogonalStates">Orthogonal states</a>:</p>
1641 <pre>
1642enum LockType
1643{
1644 NUM_LOCK,
1645 CAPS_LOCK,
1646 SCROLL_LOCK
1647};
1648
1649template&lt; LockType lockType &gt;
1650struct Off;
1651struct Active : sc::simple_state&lt;
1652 Active, Keyboard, mpl::list&lt;
1653 Off&lt; NUM_LOCK &gt;, Off&lt; CAPS_LOCK &gt;, Off&lt; SCROLL_LOCK &gt; &gt; &gt; {};
1654
1655template&lt; LockType lockType &gt;
1656struct EvPressed : sc::event&lt; EvPressed&lt; lockType &gt; &gt; {};
1657
1658template&lt; LockType lockType &gt;
1659struct On : sc::simple_state&lt;
1660 On&lt; lockType &gt;, Active::orthogonal&lt; lockType &gt; &gt;
1661{
1662 typedef sc::transition&lt;
1663 EvPressed&lt; lockType &gt;, Off&lt; lockType &gt; &gt; reactions;
1664};
1665
1666template&lt; LockType lockType &gt;
1667struct Off : sc::simple_state&lt;
1668 Off&lt; lockType &gt;, Active::orthogonal&lt; lockType &gt; &gt;
1669{
1670 typedef sc::transition&lt;
1671 EvPressed&lt; lockType &gt;, On&lt; lockType &gt; &gt; reactions;
1672};
1673</pre>
1674
1675 <h3><a name="AsynchronousStateMachines" id=
1676 "AsynchronousStateMachines">Asynchronous state machines</a></h3>
1677
1678 <h4>Why asynchronous state machines are necessary</h4>
1679
1680 <p>As the name suggests, a synchronous state machine processes each event
1681 synchronously. This behavior is implemented by the
1682 <code>state_machine</code> class template, whose <code>process_event</code>
1683 function only returns after having executed all reactions (including the
1684 ones provoked by internal events that actions might have posted). This
1685 function is strictly non-reentrant (just like all other member functions,
1686 so <code>state_machine&lt;&gt;</code> is not thread-safe). This makes it
1687 difficult for two <code>state_machine&lt;&gt;</code> subtype objects to
1688 communicate via events in a bi-directional fashion correctly, <b>even in a
1689 single-threaded program</b>. For example, state machine <code>A</code> is
1690 in the middle of processing an external event. Inside an action, it decides
1691 to send a new event to state machine <code>B</code> (by calling
1692 <code>B::process_event()</code>). It then "waits" for B to send back an
1693 answer via a <code>boost::function&lt;&gt;</code>-like call-back, which
1694 references <code>A::process_event()</code> and was passed as a data member
1695 of the event. However, while <code>A</code> is "waiting" for <code>B</code>
1696 to send back an event, <code>A::process_event()</code> has not yet returned
1697 from processing the external event and as soon as <code>B</code> answers
1698 via the call-back, <code>A::process_event()</code> is <b>unavoidably</b>
1699 reentered. This all really happens in a single thread, that's why "wait" is
1700 in quotes.</p>
1701
1702 <h4>How it works</h4>
1703
1704 <p>The <code>asynchronous_state_machine</code> class template has none of
1705 the member functions the <code>state_machine</code> class template has.
1706 Moreover, <code>asynchronous_state_machine&lt;&gt;</code> subtype objects
1707 cannot even be created or destroyed directly. Instead, all these operations
1708 must be performed through the <code>Scheduler</code> object each
1709 asynchronous state machine is associated with. All these
1710 <code>Scheduler</code> member functions only push an appropriate item into
1711 the schedulers' queue and then return immediately. A dedicated thread will
1712 later pop the items out of the queue to have them processed.</p>
1713
1714 <p>Applications will usually first create a
1715 <code>fifo_scheduler&lt;&gt;</code> object and then call
1716 <code>fifo_scheduler&lt;&gt;::create_processor&lt;&gt;()</code> and
1717 <code>fifo_scheduler&lt;&gt;::initiate_processor()</code> to schedule the
1718 creation and initiation of one or more
1719 <code>asynchronous_state_machine&lt;&gt;</code> subtype objects. Finally,
1720 <code>fifo_scheduler&lt;&gt;::operator()()</code> is either called directly
1721 to let the machine(s) run in the current thread, or, a
1722 <code>boost::function&lt;&gt;</code> object referencing
1723 <code>operator()()</code> is passed to a new <code>boost::thread</code>.
1724 Alternatively, the latter could also be done right after constructing the
1725 <code>fifo_scheduler&lt;&gt;</code> object. In the following code, we are
1726 running one state machine in a new <code>boost::thread</code> and the other
1727 in the main thread (see the PingPong example for the full source code):</p>
1728 <pre>
1729struct Waiting;
1730struct Player :
1731 sc::asynchronous_state_machine&lt; Player, Waiting &gt;
1732{
1733 // ...
1734};
1735
1736// ...
1737
1738int main()
1739{
1740 // Create two schedulers that will wait for new events
1741 // when their event queue runs empty
1742 sc::fifo_scheduler&lt;&gt; scheduler1( true );
1743 sc::fifo_scheduler&lt;&gt; scheduler2( true );
1744
1745 // Each player is serviced by its own scheduler
1746 sc::fifo_scheduler&lt;&gt;::processor_handle player1 =
1747 scheduler1.create_processor&lt; Player &gt;( /* ... */ );
1748 scheduler1.initiate_processor( player1 );
1749 sc::fifo_scheduler&lt;&gt;::processor_handle player2 =
1750 scheduler2.create_processor&lt; Player &gt;( /* ... */ );
1751 scheduler2.initiate_processor( player2 );
1752
1753 // the initial event that will start the game
1754 boost::intrusive_ptr&lt; BallReturned &gt; pInitialBall =
1755 new BallReturned();
1756
1757 // ...
1758
1759 scheduler2.queue_event( player2, pInitialBall );
1760
1761 // ...
1762
1763 // Up until here no state machines exist yet. They
1764 // will be created when operator()() is called
1765
1766 // Run first scheduler in a new thread
1767 boost::thread otherThread( boost::bind(
1768 &amp;sc::fifo_scheduler&lt;&gt;::operator(), &amp;scheduler1, 0 ) );
1769 scheduler2(); // Run second scheduler in this thread
1770 otherThread.join();
1771
1772 return 0;
1773}
1774</pre>
1775
1776 <p>We could just as well use two boost::threads:</p>
1777 <pre>
1778int main()
1779{
1780 // ...
1781
1782 boost::thread thread1( boost::bind(
1783 &amp;sc::fifo_scheduler&lt;&gt;::operator(), &amp;scheduler1, 0 ) );
1784 boost::thread thread2( boost::bind(
1785 &amp;sc::fifo_scheduler&lt;&gt;::operator(), &amp;scheduler2, 0 ) );
1786
1787 // do something else ...
1788
1789 thread1.join();
1790 thread2.join();
1791
1792 return 0;
1793}
1794</pre>
1795
1796 <p>Or, run both machines in the same thread:</p>
1797 <pre>
1798int main()
1799{
1800 sc::fifo_scheduler&lt;&gt; scheduler1( true );
1801
1802 sc::fifo_scheduler&lt;&gt;::processor_handle player1 =
1803 scheduler1.create_processor&lt; Player &gt;( /* ... */ );
1804 sc::fifo_scheduler&lt;&gt;::processor_handle player2 =
1805 scheduler1.create_processor&lt; Player &gt;( /* ... */ );
1806
1807 // ...
1808
1809 scheduler1();
1810
1811 return 0;
1812}
1813</pre>
1814
1815 <p>In all the examples above,
1816 <code>fifo_scheduler&lt;&gt;::operator()()</code> waits on an empty event
1817 queue and will only return after a call to
1818 <code>fifo_scheduler&lt;&gt;::terminate()</code>. The <code>Player</code>
1819 state machine calls this function on its scheduler object right before
1820 terminating.</p>
1821 <hr>
1822
1823 <p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src=
1824 "../../../doc/images/valid-html401.png" alt="Valid HTML 4.01 Transitional"
1825 height="31" width="88"></a></p>
1826
1827 <p>Revised
1828 <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->03 December, 2006<!--webbot bot="Timestamp" endspan i-checksum="38512" --></p>
1829
1830 <p><i>Copyright &copy; 2003-<!--webbot bot="Timestamp" s-type="EDITED" s-format="%Y" startspan -->2006<!--webbot bot="Timestamp" endspan i-checksum="770" -->
1831 <a href="contact.html">Andreas Huber D&ouml;nni</a></i></p>
1832
1833 <p><i>Distributed under the Boost Software License, Version 1.0. (See
1834 accompanying file <a href="../../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or
1835 copy at <a href=
1836 "http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)</i></p>
1837</body>
1838</html>