| <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> | |
| <html> | |
| <head> | |
| <meta http-equiv="Content-Language" content="en-us"> | |
| <meta http-equiv="Content-Type" content="text/html; charset=us-ascii"> | |
| <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="#StateLocalStorage">What's so cool about state-local | |
| storage?</a></dt> | |
| <dt><a href="#HideInnerWorkings">How can I hide the inner workings of a | |
| state machine from its clients?</a></dt> | |
| <dt><a href="#MachineInheritance">Is it possible to inherit from a given | |
| state machine and modify its layout in the subclass?</a></dt> | |
| <dt><a href="#Uml2">What about UML2.0 features?</a></dt> | |
| <dt><a href="#AssertInStateDestructor">Why do I get an assert when I | |
| access the state machine from a state destructor?</a></dt> | |
| <dt><a href="#EmbeddedApplications">Is Boost.Statechart suitable for | |
| embedded applications?</a></dt> | |
| <dt><a href="#HardRealtime">Is your library suitable for applications | |
| with hard real-time requirements?</a></dt> | |
| <dt><a href="#TemplatedStates">With templated states I get an error that | |
| 'inner_context_type' is not defined. What's wrong?</a></dt> | |
| <dt><a href="#CompilerError">My compiler reports an error in the library | |
| code. Is this a bug in Boost.Statechart?</a></dt> | |
| <dt><a href="#DisableHistory">Is it possible to disable history for a | |
| state at runtime?</a></dt> | |
| <dt><a href="#Dll">How can I compile a state machine into a dynamic link | |
| library (DLL)?</a></dt> | |
| <dt><a href="#PolymorphicEvents">Does Boost.Statechart support | |
| polymorphic events?</a></dt> | |
| <dt><a href="#WrongExitActionOrder">Why are exit-actions called in the | |
| wrong order when I use multiple inheritance?</a></dt> | |
| </dl> | |
| <h2><a name="StateLocalStorage" id="StateLocalStorage">What's so cool about | |
| state-local storage?</a></h2> | |
| <p>This is best explained with an example:</p> | |
| <pre> | |
| struct Active; | |
| struct Stopped; | |
| struct Running; | |
| struct StopWatch : sc::state_machine< StopWatch, Active > | |
| { | |
| // startTime_ remains uninitialized, because there is no reasonable default | |
| StopWatch() : elapsedTime_( 0.0 ) {} | |
| ~StopWatch() | |
| { | |
| terminate(); | |
| } | |
| double ElapsedTime() const | |
| { | |
| // Ugly switch over the current state. | |
| if ( state_cast< const Stopped * >() != 0 ) | |
| { | |
| return elapsedTime_; | |
| } | |
| else if ( state_cast< const Running * >() != 0 ) | |
| { | |
| return elapsedTime_ + std::difftime( std::time( 0 ), startTime_ ); | |
| } | |
| else // we're terminated | |
| { | |
| throw std::bad_cast(); | |
| } | |
| } | |
| // elapsedTime_ is only meaningful when the machine is not terminated | |
| double elapsedTime_; | |
| // startTime_ is only meaningful when the machine is in Running | |
| std::time_t startTime_; | |
| }; | |
| struct Active : sc::state< Active, StopWatch, Stopped > | |
| { | |
| typedef sc::transition< EvReset, Active > reactions; | |
| Active( my_context ctx ) : my_base( ctx ) | |
| { | |
| outermost_context().elapsedTime_ = 0.0; | |
| } | |
| }; | |
| struct Running : sc::state< Running, Active > | |
| { | |
| typedef sc::transition< EvStartStop, Stopped > reactions; | |
| Running( my_context ctx ) : my_base( ctx ) | |
| { | |
| outermost_context().startTime_ = std::time( 0 ); | |
| } | |
| ~Running() | |
| { | |
| outermost_context().elapsedTime_ += | |
| std::difftime( std::time( 0 ), outermost_context().startTime_ ); | |
| } | |
| }; | |
| struct Stopped : sc::simple_state< Stopped, Active > | |
| { | |
| typedef sc::transition< EvStartStop, Running > reactions; | |
| }; | |
| </pre> | |
| <p>This StopWatch does not make any use of state-local storage while | |
| implementing the same behavior as the <a href= | |
| "tutorial.html#BasicTopicsAStopWatch">tutorial StopWatch</a>. Even though | |
| this code is probably easier to read for the untrained eye, it does have a | |
| few problems that are absent in the original:</p> | |
| <ul> | |
| <li>This StopWatch class has data members that have a meaningful value | |
| only if the state machine happens to be in a certain state. That is, the | |
| lifetimes of these variables are not identical with the one of the | |
| StopWatch object containing them. Since the lifetimes are managed by the | |
| entry and exit actions of states, we need to use an ugly switch over the | |
| current state (see <code>StopWatch::ElapsedTime()</code>) if we want to | |
| access them from a context where the current state is unclear. This | |
| essentially duplicates some of the state logic of the FSM. Therefore, | |
| whenever we need to change the layout of the state machine we will likely | |
| also need to change the ugly switch. Even worse, if we forget to change | |
| the switch, the code will probably still compile and maybe even silently | |
| do the wrong thing. Note that this is impossible with the version in the | |
| tutorial, which will at least throw an exception and often just refuse to | |
| compile. Moreover, for the tutorial StopWatch there's a much higher | |
| chance that a programmer will get a change correct the first time since | |
| the code that calculates the elapsed time is located close to the code | |
| that updates the variables</li> | |
| <li>We need to change the StopWatch class whenever we want to introduce a | |
| new variable or change the type of an already existing variable. That is, | |
| many changes in the FSM will likely lead to a change in the StopWatch | |
| class. In all FSMs that do not employ state-local storage, the | |
| <code>state_machine<></code> subtype will therefore be a change | |
| hotspot, which is a pretty sure indicator for a bad design</li> | |
| </ul> | |
| <p>Both points are not much of a problem in a small example like this, | |
| which can easily be implemented in a single translation unit by a single | |
| programmer. However, they quickly become a major problem for a big complex | |
| machine spread over multiple translation units, which are possibly even | |
| maintained by different programmers.</p> | |
| <h2><a name="HideInnerWorkings" id="HideInnerWorkings">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, Stopped > | |
| { | |
| typedef sc::transition< EvReset, Active > reactions; | |
| }; | |
| struct Running : sc::simple_state< Running, Active > | |
| { | |
| typedef sc::transition< EvStartStop, Stopped > reactions; | |
| }; | |
| struct Stopped : sc::simple_state< Stopped, Active > | |
| { | |
| typedef sc::transition< EvStartStop, Running > reactions; | |
| }; | |
| StopWatch::StopWatch() | |
| { | |
| // For example, we might want to ensure that the state | |
| // machine is already started after construction. | |
| // Alternatively, we could add our own initiate() function | |
| // to StopWatch and call the base class initiate() in the | |
| // implementation. | |
| <b>initiate();</b> | |
| } | |
| </pre> | |
| <p>The PingPong example demonstrates how the inner workings of an | |
| asynchronous_state_machine<> subclass can be hidden.</p> | |
| <h2><a name="MachineInheritance" id="MachineInheritance">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 > | |
| { | |
| typedef sc::custom_reaction< EvStart > reactions; | |
| 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="Uml2" id="Uml2">What about UML 2.0 features?</a></h2> | |
| <p>The library was designed before 2.0 came along. Therefore, if not | |
| explicitly noted otherwise, the library implements the behavior mandated by | |
| the UML1.5 standard. Here's an incomplete list of differences between the | |
| 2.0 semantics & Boost.Statechart semantics:</p> | |
| <ul> | |
| <li>All transitions are always external. Local transitions are not | |
| supported at all. Unfortunately, the UML2.0 specifications are not | |
| entirely clear how local transitions are supposed to work, see <a href= | |
| "http://thread.gmane.org/gmane.comp.lib.boost.user/18641">here</a> for | |
| more information</li> | |
| <li>There is no direct support for the UML2.0 elements entry point and | |
| exit point. However, both can easily be simulated, the former with a | |
| typedef and the latter with a state that is a template (with the | |
| transition destination as a template parameter)</li> | |
| </ul> | |
| <h2><a name="AssertInStateDestructor" id="AssertInStateDestructor">Why do I | |
| get an assert when I access the state machine from a state destructor?</a> | |
| </h2> | |
| <p>When compiled with <code>NDEBUG</code> undefined, running the following | |
| program results in a failed assert:</p> | |
| <pre>#include <boost/statechart/state_machine.hpp> | |
| #include <boost/statechart/simple_state.hpp> | |
| #include <iostream> | |
| struct Initial; | |
| struct Machine : boost::statechart::state_machine< Machine, Initial > | |
| { | |
| Machine() { someMember_ = 42; } | |
| int someMember_; | |
| }; | |
| struct Initial : boost::statechart::simple_state< Initial, Machine > | |
| { | |
| ~Initial() { std::cout << outermost_context().someMember_; } | |
| }; | |
| int main() | |
| { | |
| Machine().initiate(); | |
| return 0; | |
| }</pre> | |
| <p>The problem arises because <code>state_machine<>::~state_machine</code> | |
| inevitably destructs all remaining active states. At this time, | |
| <code>Machine::~Machine</code> has already been run, making it illegal to | |
| access any of the <code>Machine</code> members. This problem can be avoided | |
| by defining the following destructor:</p> | |
| <pre>~Machine() { terminate(); }</pre> | |
| <h2><a name="EmbeddedApplications" id="EmbeddedApplications">Is | |
| Boost.Statechart suitable for embedded applications?</a></h2> | |
| <p>It depends. As explained under <a href= | |
| "performance.html#SpeedVersusScalabilityTradeoffs">Speed versus scalability | |
| tradeoffs</a> on the Performance page, 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 time to process one event 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="HardRealtime" id="HardRealtime">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 | |
| <code>std::allocator<></code> member functions and | |
| <code>dynamic_cast</code>s. <code>std::allocator<></code> member | |
| function calls can be avoided by passing a custom allocator to | |
| <code>event<></code>, <code>state_machine<></code>, | |
| <code>asynchronous_state_machine<></code>, | |
| <code>fifo_scheduler<></code> and <code>fifo_worker<></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> | |
| <h2><a name="TemplatedStates" id="TemplatedStates">With templated states I | |
| get an error that 'inner_context_type' is not defined. What's | |
| wrong?</a></h2> | |
| <p>The following code generates such an error:</p> | |
| <pre> | |
| #include <boost/statechart/state_machine.hpp> | |
| #include <boost/statechart/simple_state.hpp> | |
| namespace sc = boost::statechart; | |
| template< typename X > struct A; | |
| struct Machine : sc::state_machine< Machine, A< int > > {}; | |
| template< typename X > struct B; | |
| template< typename X > | |
| struct A : sc::simple_state< A< X >, Machine, B< X > > {}; | |
| template< typename X > | |
| struct B : sc::simple_state< B< X >, A< X > > {}; | |
| int main() | |
| { | |
| Machine machine; | |
| machine.initiate(); | |
| return 0; | |
| } | |
| </pre> | |
| <p>If the templates <code>A</code> and <code>B</code> are replaced with | |
| normal types, the above code compiles without errors. This is rooted in the | |
| fact that C++ treats forward-declared templates differently than | |
| forward-declared types. Namely, the compiler tries to access member | |
| typedefs of <code>B< X ></code> at a point where the template has not | |
| yet been defined. Luckily, this can easily be avoided by putting all inner | |
| initial state arguments in an <code>mpl::list<></code>, as | |
| follows:</p> | |
| <pre> | |
| struct A : sc::simple_state< | |
| A< X >, Machine, mpl::list< B< X > > > {}; | |
| </pre> | |
| <p>See <a href= | |
| "http://article.gmane.org/gmane.comp.lib.boost.devel/128741">this post</a> | |
| for technical details.</p> | |
| <h2><a name="CompilerError" id="CompilerError">My compiler reports an error | |
| in the library code. Is this a bug in Boost.Statechart?</a></h2> | |
| <p>Probably not. There are several possible reasons for such compile-time | |
| errors:</p> | |
| <ol> | |
| <li>Your compiler is too buggy to compile the library, see <a href= | |
| "index.html#SupportedPlatforms">here</a> for information on the status of | |
| your compiler. If you absolutely must use such a compiler for your | |
| project, I'm afraid Boost.Statechart is not for you.</li> | |
| <li>The error is reported on a line similar to the following: | |
| <pre> | |
| BOOST_STATIC_ASSERT( ( mpl::less< | |
| orthogonal_position, | |
| typename context_type::no_of_orthogonal_regions >::value ) ); | |
| </pre>Most probably, there is an error in your code. The library has many | |
| such compile-time assertions to ensure that invalid state machines cannot be | |
| compiled (for an idea what kinds of errors are reported at compile time, see | |
| the compile-fail tests). Above each of these assertions there is a comment | |
| explaining the problem. On almost all current compilers an error in template | |
| code is accompanied by the current "instantiation stack". Very much like the | |
| call stack you see in the debugger, this "instantiation stack" allows you to | |
| trace the error back through instantiations of library code until you hit the | |
| line of your code that causes the problem. As an example, here's the MSVC7.1 | |
| error message for the code in InconsistentHistoryTest1.cpp: | |
| <pre> | |
| ...\boost\statechart\shallow_history.hpp(34) : error C2027: use of undefined type 'boost::STATIC_ASSERTION_FAILURE<x>' | |
| with | |
| [ | |
| x=false | |
| ] | |
| ...\boost\statechart\shallow_history.hpp(34) : see reference to class template instantiation 'boost::STATIC_ASSERTION_FAILURE<x>' being compiled | |
| with | |
| [ | |
| x=false | |
| ] | |
| ...\boost\statechart\simple_state.hpp(861) : see reference to class template instantiation 'boost::statechart::shallow_history<DefaultState>' being compiled | |
| with | |
| [ | |
| DefaultState=B | |
| ] | |
| ...\boost\statechart\simple_state.hpp(599) : see reference to function template instantiation 'void boost::statechart::simple_state<MostDerived,Context,InnerInitial>::deep_construct_inner_impl_non_empty::deep_construct_inner_impl<InnerList>(const boost::statechart::simple_state<MostDerived,Context,InnerInitial>::inner_context_ptr_type &,boost::statechart::simple_state<MostDerived,Context,InnerInitial>::outermost_context_base_type &)' being compiled | |
| with | |
| [ | |
| MostDerived=A, | |
| Context=InconsistentHistoryTest, | |
| InnerInitial=boost::mpl::list<boost::statechart::shallow_history<B>>, | |
| InnerList=boost::statechart::simple_state<A,InconsistentHistoryTest,boost::mpl::list<boost::statechart::shallow_history<B>>>::inner_initial_list | |
| ] | |
| ...\boost\statechart\simple_state.hpp(567) : see reference to function template instantiation 'void boost::statechart::simple_state<MostDerived,Context,InnerInitial>::deep_construct_inner<boost::statechart::simple_state<MostDerived,Context,InnerInitial>::inner_initial_list>(const boost::statechart::simple_state<MostDerived,Context,InnerInitial>::inner_context_ptr_type &,boost::statechart::simple_state<MostDerived,Context,InnerInitial>::outermost_context_base_type &)' being compiled | |
| with | |
| [ | |
| MostDerived=A, | |
| Context=InconsistentHistoryTest, | |
| InnerInitial=boost::mpl::list<boost::statechart::shallow_history<B>> | |
| ] | |
| ...\boost\statechart\simple_state.hpp(563) : while compiling class-template member function 'void boost::statechart::simple_state<MostDerived,Context,InnerInitial>::deep_construct(const boost::statechart::simple_state<MostDerived,Context,InnerInitial>::context_ptr_type & ,boost::statechart::simple_state<MostDerived,Context,InnerInitial>::outermost_context_base_type &)' | |
| with | |
| [ | |
| MostDerived=A, | |
| Context=InconsistentHistoryTest, | |
| InnerInitial=boost::mpl::list<boost::statechart::shallow_history<B>> | |
| ] | |
| ...\libs\statechart\test\InconsistentHistoryTest1.cpp(29) : see reference to class template instantiation 'boost::statechart::simple_state<MostDerived,Context,InnerInitial>' being compiled | |
| with | |
| [ | |
| MostDerived=A, | |
| Context=InconsistentHistoryTest, | |
| InnerInitial=boost::mpl::list<boost::statechart::shallow_history<B>> | |
| ] | |
| </pre>Depending on the IDE you use, it is possible that you need to switch to | |
| another window to see this full error message (e.g. for Visual Studio 2003, | |
| you need to switch to the Output window). Starting at the top and going down | |
| the list of instantiations you see that each of them is accompanied by a file | |
| name and a line number. Ignoring all files belonging to the library, we find | |
| the culprit close to the bottom in file InconsistentHistoryTest1.cpp on line | |
| 29. | |
| </li> | |
| <li>The error is reported on a line nowhere near a BOOST_STATIC_ASSERT. | |
| Use the technique described under point 2 to see what line of your code | |
| causes the problem. If your code is correct then you've found a bug in | |
| either the compiler or Boost.Statechart. Please <a href= | |
| "contact.html">send me</a> a small but complete program showing the | |
| problem. Thank you!</li> | |
| </ol> | |
| <h2><a name="DisableHistory" id="DisableHistory">Is it possible to disable | |
| history for a state at runtime?</a></h2> | |
| <p>Yes, see <a href= | |
| "reference.html#clear_shallow_history">simple_state::clear_shallow_history()</a> | |
| and <a href= | |
| "reference.html#clear_deep_history">simple_state::clear_deep_history()</a>. | |
| Calling these functions is often preferable to introducting additional | |
| normal transitions when ...</p> | |
| <ul> | |
| <li>a state with history is the target of many transitions, | |
| <b>and/or</b></li> | |
| <li>the decision to ignore history is made in a different place than | |
| the transition to a state with history</li> | |
| </ul> | |
| <h2><a name="Dll" id="Dll">How can I compile a state machine into a dynamic | |
| link library (DLL)?</a></h2> | |
| <p>Invisible to the user, the library uses static data members to implement | |
| its own speed-optimized RTTI-mechanism for <code>event<></code> and | |
| <code>simple_state<></code> subtypes. Whenever such a subtype is | |
| defined in a header file and then included in multiple TUs, the linker | |
| later needs to eliminate the duplicate definitions of static data members. | |
| This usually works flawlessly as long as all these TUs are | |
| <b>statically</b> linked into the same binary. It is a lot more complex | |
| when DLLs are involved. The TuTest*.?pp files illustrate this:</p> | |
| <ul> | |
| <li><a href="../test/TuTest.hpp">TuTest.hpp</a>: Instantiates a class | |
| template containing a static data member</li> | |
| <li><a href="../test/TuTest.cpp">TuTest.cpp</a>: Includes TuTest.hpp and | |
| is compiled into a DLL</li> | |
| <li><a href="../test/TuTestMain.cpp">TuTestMain.cpp</a>: Includes | |
| TuTest.hpp and is compiled into an executable</li> | |
| </ul> | |
| <p>Without any precautions (e.g. <code>__declspec(dllexport)</code> on MSVC | |
| compatible compilers), on most platforms both binaries (exe & dll) now | |
| contain their own instance of the static data member. Since the RTTI | |
| mechanism assumes that there is exactly one object of that member at | |
| runtime, the mechanism fails spectacularly when the process running the exe | |
| also loads the dll. Different platforms deal differently with this | |
| problem:</p> | |
| <ul> | |
| <li>On some platforms (e.g. MinGW) there simply doesn't seem to be a way | |
| to enforce that such a member only exists once at runtime. Therefore, the | |
| internal RTTI mechanism cannot be used reliably in conjunction with DLLs. | |
| Disabling it by defining <a href= | |
| "configuration.html#ApplicationDefinedMacros">BOOST_STATECHART_USE_NATIVE_RTTI</a> | |
| in all TUs will <b>usually</b> work around the problem</li> | |
| <li>MSVC-compatible compilers support <code>__declspec(dllimport)</code> | |
| and <code>__declspec(dllexport)</code>, which allow to define exactly | |
| what needs to be loaded from a DLL (see TuTest for an example how to do | |
| this). Therefore, the internal RTTI mechanism can be used but care must | |
| be taken to correctly export and import all <code>event<></code> | |
| and <code>simple_state<></code> subtypes defined in headers that | |
| are compiled into more than one binary. Alternatively, of course <a href= | |
| "configuration.html#ApplicationDefinedMacros">BOOST_STATECHART_USE_NATIVE_RTTI</a> | |
| can also be used to save the work of importing and exporting</li> | |
| </ul> | |
| <h2><a name="PolymorphicEvents" id="PolymorphicEvents">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 > | |
| { | |
| typedef mpl::list< | |
| sc::custom_reaction< EvPlayButtonPressed >, | |
| sc::custom_reaction< EvStopButtonPressed >, | |
| sc::custom_reaction< EvForwardButtonPressed > | |
| > reactions; | |
| template< class MostDerived > | |
| sc::result react( const EvButtonPressed< MostDerived > & ) | |
| { | |
| // ... | |
| } | |
| }; | |
| </pre> | |
| <h2><a name="WrongExitActionOrder" id="WrongExitActionOrder">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 statechart 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> subtypes, 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, 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> | |
| <hr> | |
| <p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src= | |
| "../../../doc/images/valid-html401.png" alt="Valid HTML 4.01 Transitional" | |
| height="31" width="88"></a></p> | |
| <p>Revised 05 January, 2008</p> | |
| <p><i>Copyright © 2003-2008 <a href="contact.html">Andreas Huber | |
| Dönni</a></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> |