Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r51656 - in sandbox/msm: boost/msm libs/msm/doc
From: christophe.j.henry_at_[hidden]
Date: 2009-03-09 07:42:37


Author: chenry
Date: 2009-03-09 07:42:35 EDT (Mon, 09 Mar 2009)
New Revision: 51656
URL: http://svn.boost.org/trac/boost/changeset/51656

Log:
performance improvements + corresponding changes in doc
Text files modified:
   sandbox/msm/boost/msm/dispatch_table.hpp | 5
   sandbox/msm/boost/msm/metafunctions.hpp | 58 +++++++++
   sandbox/msm/boost/msm/state_machine.hpp | 250 ++++++++++++++++++++++++++++++---------
   sandbox/msm/boost/msm/states.hpp | 19 ++
   sandbox/msm/libs/msm/doc/SC | 4
   sandbox/msm/libs/msm/doc/SC | 4
   sandbox/msm/libs/msm/doc/index.html | 111 ++++++++++++++++-
   7 files changed, 377 insertions(+), 74 deletions(-)

Modified: sandbox/msm/boost/msm/dispatch_table.hpp
==============================================================================
--- sandbox/msm/boost/msm/dispatch_table.hpp (original)
+++ sandbox/msm/boost/msm/dispatch_table.hpp 2009-03-09 07:42:35 EDT (Mon, 09 Mar 2009)
@@ -122,13 +122,13 @@
         // Cell initializer function object, used with mpl::for_each
         template <class Transition>
         typename ::boost::enable_if<typename has_not_real_row_tag<Transition>::type,void >::type
- operator()(Transition const&) const
+ operator()(Transition const&,boost::msm::dummy<0> = 0) const
         {
             // version for not real rows. No problem because irrelevant for process_event
         }
         template <class Transition>
         typename ::boost::disable_if<typename has_not_real_row_tag<Transition>::type,void >::type
- operator()(Transition const&) const
+ operator()(Transition const&,boost::msm::dummy<1> = 0) const
         {
             typedef typename create_stt<Fsm>::type stt;
             BOOST_STATIC_CONSTANT(int, state_id =
@@ -233,3 +233,4 @@
 
 
 #endif //BOOST_MSM_DISPATCH_TABLE_H
+

Modified: sandbox/msm/boost/msm/metafunctions.hpp
==============================================================================
--- sandbox/msm/boost/msm/metafunctions.hpp (original)
+++ sandbox/msm/boost/msm/metafunctions.hpp 2009-03-09 07:42:35 EDT (Mon, 09 Mar 2009)
@@ -31,6 +31,7 @@
 BOOST_MPL_HAS_XXX_TRAIT_DEF(concrete_exit_state)
 BOOST_MPL_HAS_XXX_TRAIT_DEF(composite_tag)
 BOOST_MPL_HAS_XXX_TRAIT_DEF(not_real_row_tag)
+BOOST_MPL_HAS_XXX_TRAIT_DEF(event_blocking_flag)
 
 namespace boost { namespace msm
 {
@@ -251,6 +252,15 @@
             ::boost::mpl::bool_<false>,
             ::boost::mpl::bool_<true> >::type type;
 };
+// returns a mpl::bool_<true> if State has any delayed event
+template <class State>
+struct has_state_delayed_events
+{
+ typedef typename ::boost::mpl::if_<
+ ::boost::mpl::empty<typename State::deferred_events>,
+ ::boost::mpl::bool_<false>,
+ ::boost::mpl::bool_<true> >::type type;
+};
 
 // Template used to create dummy entries for initial states not found in the stt.
 template< typename T1 >
@@ -338,6 +348,17 @@
 
 };
 
+// metafunction used to say if a SM has pseudo exit states
+template <class Derived>
+struct has_fsm_delayed_events
+{
+ typedef typename create_stt<Derived>::type Stt;
+ typedef typename generate_state_set<Stt>::type state_list;
+
+ typedef ::boost::mpl::bool_< ::boost::mpl::count_if<
+ state_list,has_state_delayed_events< ::boost::mpl::placeholders::_1 > >::value != 0> type;
+};
+
 template <class Transition>
 struct make_vector
 {
@@ -406,6 +427,42 @@
         ::boost::mpl::bool_<false> >::type type;
 };
 
+template <class StateType>
+struct is_state_blocking
+{
+ typedef typename ::boost::mpl::fold<
+ typename StateType::flag_list, ::boost::mpl::set<>,
+ ::boost::mpl::if_<
+ has_event_blocking_flag< ::boost::mpl::placeholders::_2>,
+ ::boost::mpl::insert< ::boost::mpl::placeholders::_1, ::boost::mpl::placeholders::_2 >,
+ ::boost::mpl::placeholders::_1 >
+ >::type blocking_flags;
+
+ typedef typename ::boost::mpl::if_<
+ ::boost::mpl::empty<blocking_flags>,
+ ::boost::mpl::bool_<false>,
+ ::boost::mpl::bool_<true> >::type type;
+};
+// returns a mpl::bool_<true> if fsm has an event blocking flag in one of its substates
+template <class StateType>
+struct has_fsm_blocking_states
+{
+ typedef typename create_stt<StateType>::type Stt;
+ typedef typename generate_state_set<Stt>::type state_list;
+
+ typedef typename ::boost::mpl::fold<
+ state_list, ::boost::mpl::set<>,
+ ::boost::mpl::if_<
+ is_state_blocking< ::boost::mpl::placeholders::_2>,
+ ::boost::mpl::insert< ::boost::mpl::placeholders::_1, ::boost::mpl::placeholders::_2 >,
+ ::boost::mpl::placeholders::_1 >
+ >::type blocking_states;
+
+ typedef typename ::boost::mpl::if_<
+ ::boost::mpl::empty<blocking_states>,
+ ::boost::mpl::bool_<false>,
+ ::boost::mpl::bool_<true> >::type type;
+};
 
 // helper to find out if a SM has an active exit state and is therefore waiting for exiting
 template <class StateType,class OwnerFct,class FSM>
@@ -433,3 +490,4 @@
 } } //boost::msm
 
 #endif // BOOST_MSM_METAFUNCTIONS_H
+

Modified: sandbox/msm/boost/msm/state_machine.hpp
==============================================================================
--- sandbox/msm/boost/msm/state_machine.hpp (original)
+++ sandbox/msm/boost/msm/state_machine.hpp 2009-03-09 07:42:35 EDT (Mon, 09 Mar 2009)
@@ -47,6 +47,8 @@
 #include <boost/msm/states.hpp>
 
 BOOST_MPL_HAS_XXX_TRAIT_DEF(accept_sig)
+BOOST_MPL_HAS_XXX_TRAIT_DEF(no_exception_thrown)
+BOOST_MPL_HAS_XXX_TRAIT_DEF(no_message_queue)
 
 namespace boost { namespace msm
 {
@@ -177,79 +179,34 @@
         typedef dispatch_table<Derived,HistoryPolicy,BaseState,CopyPolicy,complete_table,Event> table;
 
         HandledEnum ret_handled=HANDLED_FALSE;
- // if the state machine is terminated, do not handle any event
- if (is_flag_active< ::boost::msm::TerminateFlag>())
- return ::boost::make_tuple(HANDLED_TRUE,&this->m_states);
- // if the state machine is interrupted, do not handle any event
- // unless the event is the end interrupt event
- if ( is_flag_active< ::boost::msm::InterruptedFlag>() &&
- !is_flag_active< ::boost::msm::EndInterruptFlag<Event> >())
+ // if the state machine has terminate or interrupt flags, check them, otherwise skip
+ if (is_event_handling_blocked_helper<Derived,Event>())
             return ::boost::make_tuple(HANDLED_TRUE,&this->m_states);
-
- // if we are already processing an event
- if (m_event_processing)
+ // if a message queue is needed and processing is on the way
+ if (!do_pre_msg_queue_helper<Derived,Event>(evt))
         {
- // event has to be put into the queue
- execute_return (state_machine<Derived,HistoryPolicy,BaseState,CopyPolicy>::*pf) (Event const& evt) =
- &state_machine<Derived,HistoryPolicy,BaseState,CopyPolicy>::process_event;
- transition_fct f = ::boost::bind(pf,this,evt);
- m_events_queue.push(f);
+ // wait for the end of current processing
             return ::boost::make_tuple(HANDLED_TRUE,&this->m_states);
         }
         else
         {
             // event can be handled, processing
- m_event_processing = true;
             // prepare the next deferred event for handling
- deferred_fct next_deferred_event;
- if (!m_deferred_events_queue.empty())
- {
- next_deferred_event = m_deferred_events_queue.front();
- m_deferred_events_queue.pop();
- }
- typedef typename get_number_of_regions<typename Derived::initial_state>::type nr_regions;
- bool handled = false;
- try
- {
- // dispatch the event to every region
- for (int i=0; i<nr_regions::value;++i)
- {
- std::pair<int,HandledEnum> res =
- table::instance.entries[this->m_states[i]](
- *static_cast<Derived*>(this), this->m_states[i], &m_state_list[0],evt);
- this->m_states[i] = res.first;
- handled = (handled || res.second);
- }
- // if the event has not been handled and we have orthogonal zones, then
- // generate an error on every active state
- // for state machine states contained in other state machines, do not handle
- // but let the containing sm handle the error
- if (!handled && !is_contained())
- {
- for (int i=0; i<nr_regions::value;++i)
- {
- (static_cast<Derived*>(this))->no_transition(this->m_states[i],evt);
- }
- }
- }
- catch (std::exception& e)
- {
- // give a chance to the concrete state machine to handle
- (static_cast<Derived*>(this))->exception_caught(e);
- }
+ // if one defer is found in the SM, otherwise skip
+ handle_defer_helper<Derived> defer_helper(m_deferred_events_queue);
+ defer_helper.do_pre_handle_deferred();
+ // process event
+ bool handled = this->do_process_helper<Derived,Event>(evt);
             if (handled)
             {
                 ret_handled = HANDLED_TRUE;
             }
             // after handling, take care of the deferred events
- if (next_deferred_event)
- {
- next_deferred_event();
- }
- m_event_processing = false;
+ defer_helper.do_post_handle_deferred();
+
             // now check if some events were generated in a transition and was not handled
             // because of another processing, and if yes, start handling them
- process_message_queue();
+ do_post_msg_queue_helper<Derived>();
             return ::boost::make_tuple(ret_handled,&this->m_states);
         }
     }
@@ -435,6 +392,169 @@
             do_copy<mpl::bool_<CopyPolicy::shallow_copy::value> >(rhs);
         }
      }
+
+ // the following 2 functions handle the terminate/interrupt states handling
+ // if one of these states is found, the first one is used
+ template <class StateType,class Event>
+ typename ::boost::enable_if<typename has_fsm_blocking_states<StateType>::type,bool >::type
+ is_event_handling_blocked_helper( ::boost::msm::dummy<0> = 0)
+ {
+ // if the state machine is terminated, do not handle any event
+ if (is_flag_active< ::boost::msm::TerminateFlag>())
+ return true;
+ // if the state machine is interrupted, do not handle any event
+ // unless the event is the end interrupt event
+ if ( is_flag_active< ::boost::msm::InterruptedFlag>() &&
+ !is_flag_active< ::boost::msm::EndInterruptFlag<Event> >())
+ return true;
+ return false;
+ }
+ // otherwise simple handling, no flag => continue
+ template <class StateType,class Event>
+ typename ::boost::disable_if<typename has_fsm_blocking_states<StateType>::type,bool >::type
+ is_event_handling_blocked_helper( ::boost::msm::dummy<1> = 0)
+ {
+ // no terminate/interrupt states detected
+ return false;
+ }
+ // the following functions handle pre/post-process handling of a message queue
+ template <class StateType,class EventType>
+ typename ::boost::enable_if<typename has_no_message_queue<StateType>::type,bool >::type
+ do_pre_msg_queue_helper(EventType const& evt, ::boost::msm::dummy<0> = 0)
+ {
+ // no message queue needed
+ return true;
+ }
+ template <class StateType,class EventType>
+ typename ::boost::disable_if<typename has_no_message_queue<StateType>::type,bool >::type
+ do_pre_msg_queue_helper(EventType const& evt, ::boost::msm::dummy<1> = 0)
+ {
+ execute_return (state_machine<Derived,HistoryPolicy,BaseState,CopyPolicy>::*pf) (EventType const& evt) =
+ &state_machine<Derived,HistoryPolicy,BaseState,CopyPolicy>::process_event;
+ // if we are already processing an event
+ if (m_event_processing)
+ {
+ // event has to be put into the queue
+ transition_fct f = ::boost::bind(pf,this,evt);
+ m_events_queue.push(f);
+ return false;
+ }
+ // event can be handled, processing
+ m_event_processing = true;
+ return true;
+ }
+ template <class StateType>
+ typename ::boost::enable_if<typename has_no_message_queue<StateType>::type,void >::type
+ do_post_msg_queue_helper( ::boost::msm::dummy<0> = 0)
+ {
+ // no message queue needed
+ }
+ template <class StateType>
+ typename ::boost::disable_if<typename has_no_message_queue<StateType>::type,void >::type
+ do_post_msg_queue_helper( ::boost::msm::dummy<1> = 0)
+ {
+ m_event_processing = false;
+ process_message_queue();
+ }
+ // the following 2 functions handle the processing either with a try/catch protection or without
+ template <class StateType,class EventType>
+ typename ::boost::enable_if<typename has_no_exception_thrown<StateType>::type,bool >::type
+ do_process_helper(EventType const& evt, ::boost::msm::dummy<0> = 0)
+ {
+ return this->do_process_event(evt);
+ }
+ template <class StateType,class EventType>
+ typename ::boost::disable_if<typename has_no_exception_thrown<StateType>::type,bool >::type
+ do_process_helper(EventType const& evt, ::boost::msm::dummy<1> = 0)
+ {
+ try
+ {
+ return this->do_process_event(evt);
+ }
+ catch (std::exception& e)
+ {
+ // give a chance to the concrete state machine to handle
+ (static_cast<Derived*>(this))->exception_caught(e);
+ }
+ return false;
+ }
+ // handling of deferred events
+ // if none is found in the SM, take the following empty main version
+ template <class StateType, class Enable = void>
+ struct handle_defer_helper
+ {
+ handle_defer_helper(deferred_events_queue_t& a_queue){}
+ void do_pre_handle_deferred()
+ {
+ }
+
+ void do_post_handle_deferred()
+ {
+ }
+ };
+ // otherwise the standard version handling the deferred events
+ template <class StateType>
+ struct handle_defer_helper
+ <StateType, typename enable_if< typename ::boost::msm::has_fsm_delayed_events<StateType>::type >::type>
+ {
+ handle_defer_helper(deferred_events_queue_t& a_queue):events_queue(a_queue),next_deferred_event(){}
+ void do_pre_handle_deferred()
+ {
+ if (!events_queue.empty())
+ {
+ next_deferred_event = events_queue.front();
+ events_queue.pop();
+ }
+ }
+
+ void do_post_handle_deferred()
+ {
+ if (next_deferred_event)
+ {
+ next_deferred_event();
+ }
+ }
+
+ private:
+ deferred_events_queue_t& events_queue;
+ deferred_fct next_deferred_event;
+ };
+
+ // minimum event processing without exceptions, queues, etc.
+ template<class Event>
+ bool do_process_event(Event const& evt)
+ {
+ // extend the table with tables from composite states
+ typedef typename extend_table<Derived>::type complete_table;
+ // use this table as if it came directly from the user
+ typedef dispatch_table<Derived,HistoryPolicy,BaseState,CopyPolicy,
+ complete_table,Event> table;
+ typedef typename get_number_of_regions<typename Derived::initial_state>::type nr_regions;
+
+ bool handled = false;
+ // dispatch the event to every region
+ for (int i=0; i<nr_regions::value;++i)
+ {
+ std::pair<int,HandledEnum> res =
+ table::instance.entries[this->m_states[i]](
+ *static_cast<Derived*>(this), this->m_states[i], &m_state_list[0],evt);
+ this->m_states[i] = res.first;
+ handled = (handled || res.second);
+ }
+ // if the event has not been handled and we have orthogonal zones, then
+ // generate an error on every active state
+ // for state machine states contained in other state machines, do not handle
+ // but let the containing sm handle the error
+ if (!handled && !is_contained())
+ {
+ for (int i=0; i<nr_regions::value;++i)
+ {
+ (static_cast<Derived*>(this))->no_transition(this->m_states[i],evt);
+ }
+ }
+ return handled;
+ }
+
     // default row arguments for the compilers which accept this
     template <class Event>
     bool no_guard(Event const&){return true;}
@@ -757,14 +877,24 @@
     private:
         // helper function, helps hiding the forward function for non-state machines states.
         template <class T>
- typename ::boost::enable_if<typename is_composite_state<T>::type,void >::type
+ typename ::boost::enable_if<
+ typename ::boost::mpl::and_<
+ typename is_composite_state<T>::type,
+ typename ::boost::mpl::not_<
+ typename has_non_forwarding_flag<Flag>::type>::type >::type
+ ,void >::type
             helper (flag_handler* an_entry,int offset,boost::msm::dummy<0> = 0 )
         {
             // composite => forward
             an_entry[offset] = &FlagHandler<T,Flag>::forward;
         }
         template <class T>
- typename ::boost::disable_if<typename is_composite_state<T>::type,void >::type
+ typename ::boost::disable_if<
+ typename ::boost::mpl::and_<
+ typename is_composite_state<T>::type,
+ typename ::boost::mpl::not_<
+ typename has_non_forwarding_flag<Flag>::type>::type >::type
+ ,void >::type
             helper (flag_handler* an_entry,int offset,boost::msm::dummy<1> = 0 )
         {
             // default no flag

Modified: sandbox/msm/boost/msm/states.hpp
==============================================================================
--- sandbox/msm/boost/msm/states.hpp (original)
+++ sandbox/msm/boost/msm/states.hpp 2009-03-09 07:42:35 EDT (Mon, 09 Mar 2009)
@@ -24,6 +24,7 @@
 BOOST_MPL_HAS_XXX_TRAIT_DEF(no_automatic_create)
 BOOST_MPL_HAS_XXX_TRAIT_DEF(direct_entry)
 BOOST_MPL_HAS_XXX_TRAIT_DEF(explicit_entry_state)
+BOOST_MPL_HAS_XXX_TRAIT_DEF(non_forwarding_flag)
 
 namespace boost { namespace msm
 {
@@ -86,10 +87,21 @@
 };
 
 // flags used internally to handle terminate / interrupt states
-struct TerminateFlag {};
-struct InterruptedFlag {};
+struct TerminateFlag
+{
+ typedef int non_forwarding_flag;
+ typedef int event_blocking_flag;
+};
+struct InterruptedFlag
+{
+ typedef int non_forwarding_flag;
+ typedef int event_blocking_flag;
+};
 template <class EndEvent>
-struct EndInterruptFlag {};
+struct EndInterruptFlag
+{
+ typedef int non_forwarding_flag;
+};
 
 // terminate state simply defines the TerminateFlag flag
 // template argument: pointer-to-fsm policy
@@ -226,3 +238,4 @@
 }}
 
 #endif //BOOST_MSM_STATES_H
+

Modified: sandbox/msm/libs/msm/doc/SC Composite.cpp
==============================================================================
--- sandbox/msm/libs/msm/doc/SC Composite.cpp (original)
+++ sandbox/msm/libs/msm/doc/SC Composite.cpp 2009-03-09 07:42:35 EDT (Mon, 09 Mar 2009)
@@ -157,6 +157,10 @@
     // Concrete FSM implementation
     struct player : public state_machine<player>
     {
+ // no need for exception handling or message queue
+ typedef int no_exception_thrown;
+ typedef int no_message_queue;
+
         // The list of FSM states
         struct Empty : public state<>
         {

Modified: sandbox/msm/libs/msm/doc/SC Simple.cpp
==============================================================================
--- sandbox/msm/libs/msm/doc/SC Simple.cpp (original)
+++ sandbox/msm/libs/msm/doc/SC Simple.cpp 2009-03-09 07:42:35 EDT (Mon, 09 Mar 2009)
@@ -124,6 +124,10 @@
     // Concrete FSM implementation
     struct player : public state_machine<player>
     {
+ // no need for exception handling or message queue
+ typedef int no_exception_thrown;
+ typedef int no_message_queue;
+
         // The list of FSM states
         struct Empty : public state<>
         {

Modified: sandbox/msm/libs/msm/doc/index.html
==============================================================================
--- sandbox/msm/libs/msm/doc/index.html (original)
+++ sandbox/msm/libs/msm/doc/index.html 2009-03-09 07:42:35 EDT (Mon, 09 Mar 2009)
@@ -6,7 +6,7 @@
         <META NAME="GENERATOR" CONTENT="OpenOffice.org 3.0 (Win32)">
         <META NAME="CREATED" CONTENT="20080922;21044300">
         <META NAME="CHANGEDBY" CONTENT="Christophe Henry">
- <META NAME="CHANGED" CONTENT="20090217;12000">
+ <META NAME="CHANGED" CONTENT="20090309;12175000">
         <META NAME="Info 1" CONTENT="">
         <META NAME="Info 2" CONTENT="">
         <META NAME="Info 3" CONTENT="">
@@ -17,6 +17,7 @@
         <META NAME="CHANGEDBY" CONTENT="Christophe Henry">
         <META NAME="CHANGEDBY" CONTENT="Christophe Henry">
         <META NAME="CHANGEDBY" CONTENT="Christophe Henry">
+ <META NAME="CHANGEDBY" CONTENT="Christophe Henry">
         <META NAME="CHANGEDBY" CONTENT="xtoff">
         <META NAME="CHANGEDBY" CONTENT="xtoff">
         <META NAME="CHANGEDBY" CONTENT="xtoff">
@@ -80,6 +81,7 @@
         <LI><P>Copying</P>
         <LI><P>Exceptions</P>
         <LI><P>Helpers methods</P>
+ <LI><P>Getting more speed</P>
 </UL>
 <P>Customizing states</P>
 <UL>
@@ -1935,6 +1937,73 @@
 </UL>
 <P><BR><BR>
 </P>
+<H2 CLASS="western"><A NAME="Getting more speed|outline"></A><CODE><FONT COLOR="#000000"><FONT FACE="Albany, sans-serif"><FONT SIZE=4>Getting
+more speed</FONT></FONT></FONT></CODE></H2>
+<P><CODE><FONT COLOR="#000000"><FONT FACE="Times New Roman, serif"><FONT SIZE=3>Msm
+is offering many features at a high-speed, but sometimes, for example
+in embedded systems, you need more speed and are ready to give up
+some features in exchange.</FONT></FONT></FONT></CODE></P>
+<P><CODE><FONT COLOR="#000000"><FONT FACE="Times New Roman, serif"><FONT SIZE=3>A
+</FONT></FONT></FONT></CODE><CODE><FONT COLOR="#000000"><FONT FACE="Courier New, monospace"><FONT SIZE=3>process_event</FONT></FONT></FONT></CODE><CODE><FONT COLOR="#000000"><FONT FACE="Times New Roman, serif"><FONT SIZE=3>
+is doing 5 different jobs:</FONT></FONT></FONT></CODE></P>
+<UL>
+ <LI><P><CODE><FONT COLOR="#000000"><FONT FACE="Times New Roman, serif"><FONT SIZE=3>checking
+ for terminate/interrupt states</FONT></FONT></FONT></CODE></P>
+ <LI><P><CODE><FONT COLOR="#000000"><FONT FACE="Times New Roman, serif"><FONT SIZE=3>handling
+ the message queue (for entry/exit/transition actions generating
+ themselves events)</FONT></FONT></FONT></CODE></P>
+ <LI><P><CODE><FONT COLOR="#000000"><FONT FACE="Times New Roman, serif"><FONT SIZE=3>handling
+ deferred events</FONT></FONT></FONT></CODE></P>
+ <LI><P><CODE><FONT COLOR="#000000"><FONT FACE="Times New Roman, serif"><FONT SIZE=3>catching
+ exceptions</FONT></FONT></FONT></CODE></P>
+ <LI><P><CODE><FONT COLOR="#000000"><FONT FACE="Times New Roman, serif"><FONT SIZE=3>handling
+ the state switching and action calls</FONT></FONT></FONT></CODE></P>
+</UL>
+<P><BR><BR>
+</P>
+<P><CODE><FONT COLOR="#000000"><FONT FACE="Times New Roman, serif"><FONT SIZE=3>Of
+these jobs, only the last is absolutely necessary to a state machine
+(its core job), the other ones are nice-to-haves which cost CPU time.
+In many cases, it is not so important, but in embedded systems, this
+can lead to ad-hoc state machine implementations.</FONT></FONT></FONT></CODE></P>
+<P><CODE><FONT COLOR="#000000"><FONT FACE="Times New Roman, serif"><FONT SIZE=3>Msm
+detects itself if a concrete state machine makes use of
+terminate/interrupt states and deferred events and deactivates them
+if not used. For the other two, if you want them out, you need to
+help by indicating in your implementation that you want them out.
+This is done with two simple typedefs, for example:</FONT></FONT></FONT></CODE></P>
+<P STYLE="margin-bottom: 0cm"><CODE><FONT COLOR="#000000"> </FONT></CODE><CODE><FONT COLOR="#000000">
+ </FONT></CODE><CODE><FONT COLOR="#008000"><FONT FACE="Times New Roman, serif"><FONT SIZE=3><SPAN LANG="">//
+Concrete FSM implementation </SPAN></FONT></FONT></FONT></CODE>
+</P>
+<P STYLE="margin-bottom: 0cm"><FONT COLOR="#000000"> </FONT><FONT SIZE=3><FONT COLOR="#0000ff"><SPAN LANG="">struct</SPAN></FONT><FONT COLOR="#000000"><SPAN LANG="">
+</SPAN></FONT><FONT COLOR="#030003"><SPAN LANG="">player</SPAN></FONT><FONT COLOR="#000000"><SPAN LANG="">
+: </SPAN></FONT><FONT COLOR="#0000ff"><SPAN LANG="">public</SPAN></FONT><FONT COLOR="#000000"><SPAN LANG="">
+</SPAN></FONT><FONT COLOR="#030003"><SPAN LANG="">state_machine</SPAN></FONT><FONT COLOR="#000000"><SPAN LANG="">&lt;</SPAN></FONT><FONT COLOR="#030003"><SPAN LANG="">player</SPAN></FONT><FONT COLOR="#000000"><SPAN LANG="">&gt;</SPAN></FONT></FONT></P>
+<P LANG="" STYLE="margin-bottom: 0cm"><FONT COLOR="#000000"> <FONT SIZE=3>{</FONT></FONT></P>
+<P STYLE="margin-bottom: 0cm"><FONT COLOR="#000000"> </FONT><FONT SIZE=3><FONT COLOR="#008000"><SPAN LANG="">//
+no need for exception handling or message queue</SPAN></FONT></FONT></P>
+<P STYLE="margin-bottom: 0cm"><FONT COLOR="#000000"> </FONT><FONT SIZE=3><FONT COLOR="#0000ff"><SPAN LANG="">typedef</SPAN></FONT><FONT COLOR="#000000"><SPAN LANG="">
+</SPAN></FONT><FONT COLOR="#0000ff"><SPAN LANG="">int</SPAN></FONT><FONT COLOR="#000000"><SPAN LANG="">
+</SPAN></FONT><FONT COLOR="#030003"><SPAN LANG="">no_exception_thrown</SPAN></FONT><FONT COLOR="#000000"><SPAN LANG="">;</SPAN></FONT></FONT></P>
+<P STYLE="margin-bottom: 0cm"><FONT COLOR="#000000"> </FONT><FONT SIZE=3><FONT COLOR="#0000ff"><SPAN LANG="">typedef</SPAN></FONT><FONT COLOR="#000000"><SPAN LANG="">
+</SPAN></FONT><FONT COLOR="#0000ff"><SPAN LANG="">int</SPAN></FONT><FONT COLOR="#000000"><SPAN LANG="">
+</SPAN></FONT><FONT COLOR="#030003"><SPAN LANG="">no_message_queue</SPAN></FONT><FONT COLOR="#000000"><SPAN LANG="">;</SPAN></FONT></FONT></P>
+<P STYLE="margin-bottom: 0cm"><CODE><FONT COLOR="#000000">
+</FONT></CODE><CODE><FONT COLOR="#000000"><FONT SIZE=3><SPAN LANG="">...</SPAN></FONT></FONT></CODE><CODE><FONT COLOR="#008000"><FONT FACE="Times New Roman, serif"><FONT SIZE=3><SPAN LANG="">//
+rest of implementation</SPAN></FONT></FONT></FONT></CODE></P>
+<P><BR><BR>
+</P>
+<P><CODE><FONT COLOR="#000000"><FONT FACE="Times New Roman, serif"><FONT SIZE=3><SPAN LANG="">What
+is the gain? It will depend on your compiler and target system, so
+please refer to the performance page
+(where an example is also provided). If you use none of these
+nice-to-haves, a </SPAN></FONT></FONT></FONT></CODE><CODE><FONT COLOR="#000000"><FONT FACE="Courier New, monospace"><FONT SIZE=3><SPAN LANG="">process_event</SPAN></FONT></FONT></FONT></CODE><CODE><FONT COLOR="#000000"><FONT FACE="Times New Roman, serif"><FONT SIZE=3><SPAN LANG="">
+can execute up to 4 times faster. On my Q6600, an average transition
+execution lasts 45ns with a full state machine, 10ns in the minimal
+case.</SPAN></FONT></FONT></FONT></CODE></P>
+<P STYLE="margin-bottom: 0cm"><BR>
+</P>
 <H1 CLASS="western"><A NAME="8.Customizing states|outline"></A><CODE><FONT COLOR="#000000"><FONT FACE="Arial, sans-serif"><FONT SIZE=4 STYLE="font-size: 16pt"><SPAN STYLE="font-style: normal">Customizing
 states</SPAN></FONT></FONT></FONT></CODE></H1>
 <P>By default, all states derive from msm::default_base_state, which
@@ -2109,29 +2178,53 @@
 have a look at the example using accept <A HREF="SM-0arg.cpp">with 0
 argument</A>, with 1, and <A HREF="SM-3arg.cpp">with
 3</A>.</FONT></FONT></FONT></P>
-<H1 CLASS="western"><A NAME="8.Performance|outline"></A>Performance</H1>
+<H1 CLASS="western"><A NAME="9.Performance|outline"></A><A NAME="8.Performance|outline"></A>
+Performance</H1>
 <P>Tests were made on different PCs running either Windows XP and
 Vista and compiled with VC9 SP1 or Ubuntu and compiled with g++
 4.2.3.</P>
 <P>For these tests, the same player state machine was written using
 Boost.Statechart and Msm, as a <A HREF="SC%20Simple.cpp">state
 machine with only simple states</A> and as a <A HREF="SC%20Composite.cpp">state
-machine with a composite state</A>.
+machine with a composite state</A>. As these simple machines need no
+terminate/interrupt states, no message queue and have no-throw
+guarantee on their actions, the tests are made in full- and minimum-
+functionalities.</P>
+<P>Minimum (no exception handling, no message queue):</P>
+<P>VC9:</P>
+<UL>
+ <LI><P>the simple test completes 38 times faster with Msm than with
+ Boost.Statechart</P>
+ <LI><P>the composite test completes 4 times faster with Msm</P>
+</UL>
+<P>gcc 4.2.3:</P>
+<UL>
+ <LI><P>the simple test completes 16 times faster with Msm</P>
+ <LI><P>the composite test completes 9 times faster with Msm</P>
+</UL>
+<P>gcc 3.3:</P>
+<UL>
+ <LI><P>the simple test completes 9-12 times faster with Msm</P>
+ <LI><P>the composite compile but does not work (events of composites
+ lead to no_transition)</P>
+</UL>
+<P><BR><BR>
 </P>
+<P>Full:</P>
 <P>VC9:</P>
 <UL>
- <LI><P>the simple test completes 9-10 times faster with Msm than
- with Boost.Statechart</P>
- <LI><P>the composite test completes 3-3,5 times faster with Msm</P>
+ <LI><P>the simple test completes 12 times faster with Msm than with
+ Boost.Statechart</P>
+ <LI><P>the composite test completes 3 times faster with Msm</P>
 </UL>
 <P>gcc 4.2.3:</P>
 <UL>
- <LI><P>the simple test completes 6 times faster with Msm</P>
- <LI><P>the composite test completes 4-5 times faster with Msm</P>
+ <LI><P>the simple test completes 10 times faster with Msm</P>
+ <LI><P>the composite test completes 9-10 times faster with Msm</P>
 </UL>
 <P>gcc 3.3:</P>
 <UL>
- <LI><P>the simple test completes 3 times faster with Msm</P>
+ <LI><P>the simple test completes 9 times faster with Msm</P>
         <LI><P>the composite compile but does not work (events of composites
         lead to no_transition)</P>
 </UL>


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk