Files
statechart/doc/faq.html
Andreas Huber 5efc93cc69 - Finished reference documentation
- Updated Copyright notices


[SVN r21607]
2004-01-11 23:08:54 +00:00

264 lines
9.6 KiB
HTML

<html>
<head>
<meta http-equiv="Content-Language" content="en-us">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<link rel="stylesheet" type="text/css" href="../../../boost.css">
<title>The boost::fsm library - FAQ</title>
</head>
<body link="#0000ff" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary="header">
<tr>
<td valign="top" width="300">
<h3><a href="../../../index.htm">
<img alt="C++ Boost" src="../../../c++boost.gif" border="0" width="277" height="86"></a></h3>
</td>
<td valign="top">
<h1 align="center">The boost::fsm library</h1>
<h2 align="center">Frequently Asked Questions (FAQs)</h2>
</td>
</tr>
</table>
<hr>
<dl class="page-index">
<dt><a href="#Does boost::fsm support polymorphic events">Does boost::fsm
support polymorphic events?</a></dt>
<dt>
<a href="#How can I hide the inner workings of a state machine from its clients">
How can I hide the inner workings of a state machine from its clients?</a></dt>
<dt>
<a href="#Is it possible to inherit from a given state machine and modify its layout in the subclass">
Is it possible to inherit from a given state machine and modify its layout
in the subclass?</a></dt>
<dt>
<a href="#Why are exit-actions called in the wrong order when I use multiple inheritance">
Why are exit-actions called in the wrong order when I use multiple
inheritance?</a></dt>
</dl>
<h2><a name="Does boost::fsm support polymorphic events">Does boost::fsm
support polymorphic events?</a></h2>
<p>No. Although events can be derived from each other to write common code
only once, <a href="definitions.html#Reaction">reactions</a> can only be
defined for most-derived events.</p>
<p>Example:</p>
<pre>template&lt; class MostDerived &gt;
struct EvButtonPressed : fsm::event&lt; MostDerived &gt;
{
// common code
};
struct EvPlayButtonPressed :
EvButtonPressed&lt; EvPlayButtonPressed &gt; {};
struct EvStopButtonPressed :
EvButtonPressed&lt; EvStopButtonPressed &gt; {};
struct EvForwardButtonPressed :
EvButtonPressed&lt; EvForwardButtonPressed &gt; {};
/* ... */
// We want to turn the player on, no matter what button we
// press in the Off state. Although we can write the reaction
// code only once, we must mention all most-derived events in
// the reaction list.
struct Off : fsm::simple_state&lt; Off, Mp3Player, mpl::list&lt;
fsm::custom_reaction&lt; EvPlayButtonPressed &gt;,
fsm::custom_reaction&lt; EvStopButtonPressed &gt;,
fsm::custom_reaction&lt; EvForwardButtonPressed &gt; &gt; &gt;
{
template&lt; class MostDerived &gt;
fsm::result react( const EvButtonPressed&lt; MostDerived &gt; &amp; )
{
// ...
}
};</pre>
<h2>
<a name="How can I hide the inner workings of a state machine from its clients">
How can I hide the inner workings of a state machine from its clients?</a></h2>
<p>To see why and how this is possible it is important to recall the following
facts:</p>
<ul>
<li>Member functions of a C++ class template are instantiated at the point
where they're actually called. If the function is never called, it will not
be instantiated and not a single assembly instruction will ever be
generated.</li>
<li>The <code>InitialState</code> template parameter of <code>
fsm::state_machine</code> can be an incomplete type (i.e. forward declared).</li>
</ul>
<p>The class template member function <code>state_machine&lt;&gt;::initiate()</code>
creates an object of the initial state. So, the definition of this state must
be known before the compiler reaches the point where <code>initiate()</code>
is called. To be able to hide the initial state of a state machine in a .cpp
file we must therefore no longer let clients call <code>initiate()</code>.
Instead, we do so in the .cpp file, at a point where the full definition of
the initial state is known.</p>
<p>Example:</p>
<p>StopWatch.hpp:</p>
<pre>// define events ...
struct Active; // the only visible forward
struct StopWatch : fsm::state_machine&lt; StopWatch, Active &gt;
{
StopWatch();
};</pre>
<p>StopWatch.cpp:</p>
<pre>struct Stopped;
struct Active : fsm::simple_state&lt; Active, StopWatch,
fsm::transition&lt; EvReset, Active &gt;, Stopped &gt; {};
struct Running : fsm::simple_state&lt; Running, Active,
fsm::transition&lt; EvStartStop, Stopped &gt; &gt; {};
struct Stopped : fsm::simple_state&lt; Stopped, Active,
fsm::transition&lt; EvStartStop, Running &gt; &gt; {};
StopWatch::StopWatch()
{
// For example, we might want to ensure that the state
// machine is already started after construction.
// Alternatively we could also provide the client with
// a Start() function...
<b>initiate();</b>
}</pre>
<h2>
<a name="Is it possible to inherit from a given state machine and modify its layout in the subclass">
Is it possible to inherit from a given state machine and modify its layout in
the subclass?</a></h2>
<p>Yes, but contrary to what some FSM code generators allow, boost::fsm
machines can do so only in a way that was foreseen by the designer of the base
state machine: </p>
<pre>struct EvStart : fsm::event&lt; EvStart &gt; {};
struct Idle;
struct PumpBase : fsm::state_machine&lt; PumpBase, Idle &gt;
{
<b>virtual fsm::result react(
</b> <b>Idle &amp; idle, const EvStart &amp; ) const;
</b>};
struct Idle : fsm::simple_state&lt; Idle, PumpBase,
fsm::custom_reaction&lt; EvStart &gt; &gt;
{
fsm::result react( const EvStart &amp; evt )
{
<b>return context&lt; PumpBase &gt;().react( *this, evt );</b>
}
};
struct Running : fsm::simple_state&lt; Running, PumpBase &gt; {};
fsm::result PumpBase::react(
Idle &amp; idle, const EvStart &amp; ) const
{
<b>return idle.transit&lt; Running &gt;();
</b>}
struct MyRunning : fsm::simple_state&lt; MyRunning, PumpBase &gt; {};
struct MyPump : PumpBase
{
virtual fsm::result react(
Idle &amp; idle, const EvStart &amp; ) const
{
<b>return idle.transit&lt; MyRunning &gt;();
</b> }
};</pre>
<h2>
<a name="Why are exit-actions called in the wrong order when I use multiple inheritance">
Why are exit-actions called in the wrong order when I use multiple
inheritance?</a></h2>
<p>They definitely aren't for the <code>simple_state</code> and <code>state</code>
subclasses, but the destructors of additional bases might be called in
construction order (rather than the reverse construction order):</p>
<pre>#include &lt;boost/fsm/state_machine.hpp&gt;
#include &lt;boost/fsm/simple_state.hpp&gt;
namespace fsm = boost::fsm;
class EntryExitDisplayer
{
protected:
EntryExitDisplayer( const char * pName ) :
pName_( pName )
{
std::cout &lt;&lt; pName_ &lt;&lt; &quot; entered\n&quot;;
}
~EntryExitDisplayer()
{
std::cout &lt;&lt; pName_ &lt;&lt; &quot; exited\n&quot;;
}
private:
const char * const pName_;
};
struct Outer;
struct Machine : fsm::state_machine&lt; Machine, Outer &gt; {};
struct Inner;
struct Outer : EntryExitDisplayer, fsm::simple_state&lt;
Outer, Machine, fsm::no_reactions, Inner &gt;
{
Outer() : EntryExitDisplayer( &quot;Outer&quot; ) {}
};
struct Inner : EntryExitDisplayer,
fsm::simple_state&lt; Inner, Outer &gt;
{
Inner() : EntryExitDisplayer( &quot;Inner&quot; ) {}
};
int main()
{
Machine myMachine;
myMachine.initiate();
return 0;
}</pre>
<p>This program will produce the following output:</p>
<pre>Outer entered
Inner entered
Outer exited
Inner exited</pre>
<p>That is, the <b><code>EntryExitDisplayer</code> base class portion</b> of
<code>Outer</code> is destructed before the one of <code>Inner</code> although
<code>Inner::~Inner()</code> is called before <code>Outer::~Outer()</code>.
This somewhat counter-intuitive behavior is caused by the following facts: </p>
<ul>
<li>The <code>simple_state&lt;&gt;</code> base class portion of <code>Inner</code>
is responsible to destruct <code>Outer</code></li>
<li>Destructors of base class portions are called in the reverse order of
construction</li>
</ul>
<p>So, when the <code>Outer</code> destructor is called the call stack looks
as follows:</p>
<pre>Outer::~Outer()
simple_state&lt; Inner, ... &gt;::~simple_state()
Inner::~Inner()</pre>
<p>Note that <code>Inner::~Inner()</code> did not yet have a chance to destroy
its <code>EntryExitDisplayer</code> base class portion, as it first has to
call the destructor of the <b>second</b> base class. Now <code>Outer::~Outer()</code>
will first destruct its <code>simple_state&lt; Outer, ... &gt;</code> base class
portion and then do the same with its <code>EntryExitDisplayer</code> base
class portion. The stack then unwinds back to <code>Inner::~Inner()</code>,
which can then finally finish by calling <code>
EntryExitDisplayer::~EntryExitDisplayer()</code>.</p>
<p>Luckily, there is an easy work-around: Always let <code>simple_state&lt;&gt;</code>
and <code>state&lt;&gt;</code> be the first base class of a state. This ensures that
destructors of additional bases are called before recursion employed by state
base destructors can alter the order of destruction.</p>
<hr>
<p>Revised
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->11 January, 2004<!--webbot bot="Timestamp" endspan i-checksum="38695" --></p>
<p><i>Copyright © <a href="mailto:ah2003@gmx.net">Andreas Huber Dönni</a>
2003-2004. Use, modification and distribution are subject to the Boost
Software License, Version 1.0. (See accompanying file
<a href="../../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy at
<a href="http://www.boost.org/LICENSE_1_0.txt">
http://www.boost.org/LICENSE_1_0.txt</a>)</i></p>
</body>
</html>