320 lines
14 KiB
HTML
320 lines
14 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 6.0">
|
||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
||
<link rel="stylesheet" type="text/css" href="../../../boost.css">
|
||
<title>The Boost Statechart 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="../../../boost.png" border="0" width="277" height="86"></a></h3>
|
||
</td>
|
||
<td valign="top">
|
||
<h1 align="center">The Boost Statechart Library</h1>
|
||
<h2 align="center">Frequently Asked Questions (FAQs)</h2>
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
<hr>
|
||
<dl class="page-index">
|
||
<dt><a href="#Does_Boost.Statechart_support_polymorphic_events">Does Boost.Statechart
|
||
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>
|
||
<dt><a href="#Is_Boost.Statechart_suitable_for_embedded_applications">Is Boost.Statechart suitable for embedded applications?</a></dt>
|
||
<dt>
|
||
<a href="#Is_your_library_suitable_for_applications_with_hard_real-time_requirements">
|
||
Is your library suitable for applications with hard real-time requirements</a>?</dt>
|
||
</dl>
|
||
<h2><a name="Does_Boost.Statechart_support_polymorphic_events">Does Boost.Statechart
|
||
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< class MostDerived >
|
||
struct EvButtonPressed : sc::event< MostDerived >
|
||
{
|
||
// common code
|
||
};
|
||
|
||
struct EvPlayButtonPressed :
|
||
EvButtonPressed< EvPlayButtonPressed > {};
|
||
struct EvStopButtonPressed :
|
||
EvButtonPressed< EvStopButtonPressed > {};
|
||
struct EvForwardButtonPressed :
|
||
EvButtonPressed< EvForwardButtonPressed > {};
|
||
|
||
/* ... */
|
||
|
||
// 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 : sc::simple_state< Off, Mp3Player, mpl::list<
|
||
sc::custom_reaction< EvPlayButtonPressed >,
|
||
sc::custom_reaction< EvStopButtonPressed >,
|
||
sc::custom_reaction< EvForwardButtonPressed > > >
|
||
{
|
||
template< class MostDerived >
|
||
sc::result react( const EvButtonPressed< MostDerived > & )
|
||
{
|
||
// ...
|
||
}
|
||
};</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>
|
||
sc::state_machine</code> can be an incomplete type (i.e. forward declared).</li>
|
||
</ul>
|
||
<p>The class template member function <code>state_machine<>::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 : sc::state_machine< StopWatch, Active >
|
||
{
|
||
StopWatch();
|
||
};</pre>
|
||
<p>StopWatch.cpp:</p>
|
||
<pre>struct Stopped;
|
||
struct Active : sc::simple_state< Active, StopWatch,
|
||
sc::transition< EvReset, Active >, Stopped > {};
|
||
struct Running : sc::simple_state< Running, Active,
|
||
sc::transition< EvStartStop, Stopped > > {};
|
||
struct Stopped : sc::simple_state< Stopped, Active,
|
||
sc::transition< EvStartStop, Running > > {};
|
||
|
||
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.Statechart
|
||
machines can do so only in a way that was foreseen by the designer of the base
|
||
state machine: </p>
|
||
<pre>struct EvStart : sc::event< EvStart > {};
|
||
|
||
struct Idle;
|
||
struct PumpBase : sc::state_machine< PumpBase, Idle >
|
||
{
|
||
<b>virtual sc::result react(
|
||
</b> <b>Idle & idle, const EvStart & ) const;
|
||
</b>};
|
||
|
||
struct Idle : sc::simple_state< Idle, PumpBase,
|
||
sc::custom_reaction< EvStart > >
|
||
{
|
||
sc::result react( const EvStart & evt )
|
||
{
|
||
<b>return context< PumpBase >().react( *this, evt );</b>
|
||
}
|
||
};
|
||
|
||
struct Running : sc::simple_state< Running, PumpBase > {};
|
||
|
||
sc::result PumpBase::react(
|
||
Idle & idle, const EvStart & ) const
|
||
{
|
||
<b>return idle.transit< Running >();
|
||
</b>}
|
||
|
||
|
||
struct MyRunning : sc::simple_state< MyRunning, PumpBase > {};
|
||
|
||
struct MyPump : PumpBase
|
||
{
|
||
virtual sc::result react(
|
||
Idle & idle, const EvStart & ) const
|
||
{
|
||
<b>return idle.transit< MyRunning >();
|
||
</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><b>Update</b>: The implementation has changed considerably in this area. It
|
||
is still possible to get this behavior under rare circumstances (when an action
|
||
propagates an exception in a state machine with orthogonal regions <b>and</b> if
|
||
the state chart layout satisfies certain conditions), but it can no longer be
|
||
demonstrated with the example program below. However, the described workaround
|
||
is still valid and ensures that this behavior will never show up.</p>
|
||
<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 <boost/statechart/state_machine.hpp>
|
||
#include <boost/statechart/simple_state.hpp>
|
||
|
||
namespace sc = boost::statechart;
|
||
|
||
class EntryExitDisplayer
|
||
{
|
||
protected:
|
||
EntryExitDisplayer( const char * pName ) :
|
||
pName_( pName )
|
||
{
|
||
std::cout << pName_ << " entered\n";
|
||
}
|
||
|
||
~EntryExitDisplayer()
|
||
{
|
||
std::cout << pName_ << " exited\n";
|
||
}
|
||
|
||
private:
|
||
const char * const pName_;
|
||
};
|
||
|
||
struct Outer;
|
||
struct Machine : sc::state_machine< Machine, Outer > {};
|
||
struct Inner;
|
||
struct Outer : EntryExitDisplayer, sc::simple_state<
|
||
Outer, Machine, sc::no_reactions, Inner >
|
||
{
|
||
Outer() : EntryExitDisplayer( "Outer" ) {}
|
||
};
|
||
|
||
struct Inner : EntryExitDisplayer,
|
||
sc::simple_state< Inner, Outer >
|
||
{
|
||
Inner() : EntryExitDisplayer( "Inner" ) {}
|
||
};
|
||
|
||
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<></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< Inner, ... >::~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< Outer, ... ></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<></code>
|
||
and <code>state<></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>
|
||
<h2><a name="Is_Boost.Statechart_suitable_for_embedded_applications">Is Boost.Statechart suitable for embedded applications?</a></h2>
|
||
<p>It depends. As explained under
|
||
<a href="rationale.html#Speed versus scalability tradeoffs">Speed
|
||
versus scalability tradeoffs</a> in the Rationale, the virtually limitless scalability
|
||
offered by this library does have its
|
||
price. Especially small and simple FSMs can easily be implemented so that they
|
||
consume fewer cycles and less memory and occupy less code space in the
|
||
executable. Here are some obviously <b>very rough</b> estimates:</p>
|
||
<ul>
|
||
<li>For a state machine with at most one simultaneously active state (that
|
||
is, the machine is flat and does not have orthogonal regions) with trivial
|
||
actions, customized memory management and compiled with a good optimizing
|
||
compiler, a Pentium 4 class CPU should not spend more than 1000 cycles
|
||
inside <code>state_machine<>::process_event()</code>. This worst-case
|
||
dispatch and transition time scales more or less linearly with the number of
|
||
simultaneously active states for more complex state machines, with the
|
||
typical average being much lower than that. So, a fairly complex machine
|
||
with at most 10 simultaneously active states running on a 100MHz CPU should
|
||
be able to process more than 10'000 events per second</li>
|
||
<li>A single state machine object uses typically less than 1KB of memory,
|
||
even if it implements a very complex machine</li>
|
||
<li>For code size, it is difficult to give a concrete guideline but tests
|
||
with the BitMachine example suggest that code size scales more or less
|
||
linearly with the number of states (transitions seem to have only little
|
||
impact). When compiled with MSVC7.1 on Windows, 32 states and 224
|
||
transitions seem to fit in ~108KB executable code (with all optimizations
|
||
turned on).<br>
|
||
Moreover, the library can be compiled with C++ RTTI and exception handling turned off,
|
||
resulting in significant savings on most platforms</li>
|
||
</ul>
|
||
<p>As mentioned above, these are very rough estimates derived from the use of
|
||
the library on a desktop PC, so they should only be used to decide whether there
|
||
is a point in making your own performance tests on your target platform.</p>
|
||
<h2>
|
||
<a name="Is_your_library_suitable_for_applications_with_hard_real-time_requirements">
|
||
Is your library suitable for applications with hard real-time requirements?</a></h2>
|
||
<p>Yes. Out of the box, the only operations taking potentially non-deterministic
|
||
time that the library performs are calls to
|
||
global <code>operator new</code> and <code>dynamic_cast</code>s. Global <code>
|
||
operator new</code> calls can be avoided by passing a custom allocator to
|
||
<code>state_machine<></code> <b>and</b> by giving all state classes a custom <code>
|
||
operator new</code>. <code>dynamic_cast</code>s can be avoided by not calling the
|
||
<code>state_cast<></code> member functions of <code>state_machine<></code>,
|
||
<code>simple_state<></code> and <code>state<></code> but using the
|
||
deterministic variant <code>state_downcast<></code> instead.</p>
|
||
<hr>
|
||
<p>Revised
|
||
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->10 May, 2005<!--webbot bot="Timestamp" endspan i-checksum="13987" --></p>
|
||
<p><i><EFBFBD> Copyright <a href="mailto:ahd6974-spamgroupstrap@yahoo.com">Andreas Huber D<>nni</a>
|
||
2003-2005. <font color="#FF0000"><b>The link refers to a
|
||
<a href="http://en.wikipedia.org/wiki/Honeypot">spam honeypot</a>. Please remove the words spam and trap
|
||
to obtain my real address.</b></font></i></p>
|
||
<p><i>Distributed under 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>
|