$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
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=""><</SPAN></FONT><FONT COLOR="#030003"><SPAN LANG="">player</SPAN></FONT><FONT COLOR="#000000"><SPAN LANG="">></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>