$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r74320 - trunk/boost/msm/back
From: christophe.j.henry_at_[hidden]
Date: 2011-09-08 17:13:03
Author: chenry
Date: 2011-09-08 17:13:03 EDT (Thu, 08 Sep 2011)
New Revision: 74320
URL: http://svn.boost.org/trac/boost/changeset/74320
Log:
new internal transition implementation
Text files modified: 
   trunk/boost/msm/back/dispatch_table.hpp     |    63 ++++++++++--                            
   trunk/boost/msm/back/favor_compile_time.hpp |    64 ++++++++++--                            
   trunk/boost/msm/back/state_machine.hpp      |   193 +++++++++++++++++++++++++++++++++++---- 
   3 files changed, 278 insertions(+), 42 deletions(-)
Modified: trunk/boost/msm/back/dispatch_table.hpp
==============================================================================
--- trunk/boost/msm/back/dispatch_table.hpp	(original)
+++ trunk/boost/msm/back/dispatch_table.hpp	2011-09-08 17:13:03 EDT (Thu, 08 Sep 2011)
@@ -154,22 +154,47 @@
           : self(self_)
         {}
         // version for transition event not base of our event
+        // first for all transitions, then for internal ones of a fsm
         template <class Transition>
-        void init_event_base_case(Transition const&, ::boost::mpl::true_ const &) const
+        typename ::boost::disable_if<
+            typename ::boost::is_same<typename Transition::current_state_type,Fsm>::type
+        ,void>::type
+        init_event_base_case(Transition const&, ::boost::mpl::true_ const &) const
         {
             typedef typename create_stt<Fsm>::type stt; 
             BOOST_STATIC_CONSTANT(int, state_id = 
                 (get_state_id<stt,typename Transition::current_state_type>::value));
-            self->entries[state_id] = reinterpret_cast<cell>(&Transition::execute);
+            self->entries[state_id+1] = reinterpret_cast<cell>(&Transition::execute);
         }
+        template <class Transition>
+        typename ::boost::enable_if<
+            typename ::boost::is_same<typename Transition::current_state_type,Fsm>::type
+        ,void>::type
+        init_event_base_case(Transition const&, ::boost::mpl::true_ const &) const
+        {
+            self->entries[0] = reinterpret_cast<cell>(&Transition::execute);
+        }
+
         // version for transition event base of our event
+        // first for all transitions, then for internal ones of a fsm
         template <class Transition>
-        void init_event_base_case(Transition const&, ::boost::mpl::false_ const &) const
+        typename ::boost::disable_if<
+            typename ::boost::is_same<typename Transition::current_state_type,Fsm>::type
+        ,void>::type
+        init_event_base_case(Transition const&, ::boost::mpl::false_ const &) const
         {
             typedef typename create_stt<Fsm>::type stt; 
             BOOST_STATIC_CONSTANT(int, state_id = 
                 (get_state_id<stt,typename Transition::current_state_type>::value));
-            self->entries[state_id] = &Transition::execute;
+            self->entries[state_id+1] = &Transition::execute;
+        }
+        template <class Transition>
+        typename ::boost::enable_if<
+            typename ::boost::is_same<typename Transition::current_state_type,Fsm>::type
+        ,void>::type
+        init_event_base_case(Transition const&, ::boost::mpl::false_ const &) const
+        {
+            self->entries[0] = &Transition::execute;
         }
         // Cell initializer function object, used with mpl::for_each
         template <class Transition>
@@ -207,18 +232,35 @@
             typedef typename create_stt<Fsm>::type stt; 
             BOOST_STATIC_CONSTANT(int, state_id = (get_state_id<stt,State>::value));
             cell call_no_transition = &Fsm::defer_transition;
-            tofill_entries[state_id] = call_no_transition;
+            tofill_entries[state_id+1] = call_no_transition;
         }
         template <class State>
-        typename ::boost::disable_if<typename has_state_delayed_event<State,Event>::type,void >::type
+        typename ::boost::disable_if<
+            typename ::boost::mpl::or_<
+                typename has_state_delayed_event<State,Event>::type,
+                typename ::boost::is_same<State,Fsm>::type
+            >::type
+        ,void >::type
         operator()(boost::msm::wrap<State> const&,boost::msm::back::dummy<1> = 0)
         {
             typedef typename create_stt<Fsm>::type stt; 
             BOOST_STATIC_CONSTANT(int, state_id = (get_state_id<stt,State>::value));
             cell call_no_transition = &Fsm::call_no_transition;
-            tofill_entries[state_id] = call_no_transition;
+            tofill_entries[state_id+1] = call_no_transition;
+        }
+        // case for internal transitions of this fsm
+        template <class State>
+        typename ::boost::enable_if<
+            typename ::boost::mpl::and_<
+                typename ::boost::mpl::not_<typename has_state_delayed_event<State,Event>::type>::type,
+                typename ::boost::is_same<State,Fsm>::type
+            >::type
+        ,void>::type
+        operator()(boost::msm::wrap<State> const&,boost::msm::back::dummy<2> = 0)
+        {
+            cell call_no_transition = &Fsm::call_no_transition_internal;
+            tofill_entries[0] = call_no_transition;
         }
-
         dispatch_table* self;
         cell* tofill_entries;
     };
@@ -241,7 +283,7 @@
             typedef typename create_stt<Fsm>::type stt; 
             BOOST_STATIC_CONSTANT(int, state_id = (get_state_id<stt,State>::value));
             cell call_no_transition = &Fsm::default_eventless_transition;
-            tofill_entries[state_id] = call_no_transition;
+            tofill_entries[state_id+1] = call_no_transition;
         }
 
         dispatch_table* self;
@@ -308,7 +350,8 @@
     static const dispatch_table instance;
 
  public: // data members
-    cell entries[max_state];
+     // +1 => 0 is reserved for this fsm (internal transitions)
+    cell entries[max_state+1];
 };
 
 }}} // boost::msm::back
Modified: trunk/boost/msm/back/favor_compile_time.hpp
==============================================================================
--- trunk/boost/msm/back/favor_compile_time.hpp	(original)
+++ trunk/boost/msm/back/favor_compile_time.hpp	2011-09-08 17:13:03 EDT (Thu, 08 Sep 2011)
@@ -54,7 +54,9 @@
     ::boost::msm::back::HandledEnum fsmname::process_any_event( ::boost::any const& any_event)      \
     {                                                                                               \
         typedef ::boost::msm::back::recursive_get_transition_table<fsmname>::type stt;              \
-        typedef ::boost::msm::back::generate_event_set<stt>::type all_events;                       \
+        typedef ::boost::msm::back::generate_event_set<stt>::type stt_events;                       \
+        typedef fsmname::processable_events_internal_table internal_events;                         \
+        typedef ::boost::msm::back::set_insert_range<stt_events,internal_events>::type all_events;  \
         ::boost::msm::back::HandledEnum res= ::boost::msm::back::HANDLED_FALSE;                     \
         ::boost::mpl::for_each<all_events, ::boost::msm::wrap< ::boost::mpl::placeholders::_1> >    \
         (::boost::msm::back::process_any_event_helper<fsmname>(res,this,any_event));                \
@@ -118,21 +120,44 @@
         {}
         // version for transition event not base of our event
         template <class Transition>
-        void init_event_base_case(Transition const&, ::boost::mpl::true_ const &) const
+        typename ::boost::disable_if<
+            typename ::boost::is_same<typename Transition::current_state_type,Fsm>::type
+        ,void>::type
+        init_event_base_case(Transition const&, ::boost::mpl::true_ const &) const
         {
             typedef typename create_stt<Fsm>::type stt; 
             BOOST_STATIC_CONSTANT(int, state_id = 
                 (get_state_id<stt,typename Transition::current_state_type>::value));
-            self->entries[state_id].one_state.push_front(reinterpret_cast<cell>(&Transition::execute));
+            self->entries[state_id+1].one_state.push_front(reinterpret_cast<cell>(&Transition::execute));
         }
+        template <class Transition>
+        typename ::boost::enable_if<
+            typename ::boost::is_same<typename Transition::current_state_type,Fsm>::type
+        ,void>::type
+        init_event_base_case(Transition const&, ::boost::mpl::true_ const &) const
+        {
+            self->entries[0].one_state.push_front(reinterpret_cast<cell>(&Transition::execute));
+        }
+
         // version for transition event base of our event
         template <class Transition>
-        void init_event_base_case(Transition const&, ::boost::mpl::false_ const &) const
+        typename ::boost::disable_if<
+            typename ::boost::is_same<typename Transition::current_state_type,Fsm>::type
+        ,void>::type
+        init_event_base_case(Transition const&, ::boost::mpl::false_ const &) const
         {
             typedef typename create_stt<Fsm>::type stt; 
             BOOST_STATIC_CONSTANT(int, state_id = 
                 (get_state_id<stt,typename Transition::current_state_type>::value));
-            self->entries[state_id].one_state.push_front(&Transition::execute);
+            self->entries[state_id+1].one_state.push_front(&Transition::execute);
+        }
+        template <class Transition>
+        typename ::boost::enable_if<
+            typename ::boost::is_same<typename Transition::current_state_type,Fsm>::type
+        ,void>::type
+        init_event_base_case(Transition const&, ::boost::mpl::false_ const &) const
+        {
+            self->entries[0].one_state.push_front(&Transition::execute);
         }
         // Cell initializer function object, used with mpl::for_each
         template <class Transition>
@@ -174,7 +199,7 @@
                 typedef typename create_stt<Fsm>::type stt; 
                 BOOST_STATIC_CONSTANT(int, state_id = (get_state_id<stt,State>::value));
                 cell call_no_transition = &Fsm::defer_transition;
-                tofill[state_id].one_state.push_back(call_no_transition);
+                tofill[state_id+1].one_state.push_back(call_no_transition);
             }
         };
         template <int some_dummy> struct helper<true,true,some_dummy> 
@@ -185,18 +210,33 @@
                 typedef typename create_stt<Fsm>::type stt; 
                 BOOST_STATIC_CONSTANT(int, state_id = (get_state_id<stt,State>::value));
                 cell call_no_transition = &Fsm::defer_transition;
-                tofill[state_id].one_state.push_back(call_no_transition);
+                tofill[state_id+1].one_state.push_back(call_no_transition);
             }
         };
         template <int some_dummy> struct helper<false,true,some_dummy> 
         {
             template <class State>
-            static void execute(boost::msm::wrap<State> const&,chain_row* tofill)
+            static
+            typename ::boost::enable_if<
+                typename ::boost::is_same<State,Fsm>::type
+            ,void>::type
+            execute(boost::msm::wrap<State> const&,chain_row* tofill,boost::msm::back::dummy<0> = 0)
+            {
+                // for internal tables
+                cell call_no_transition_internal = &Fsm::call_no_transition;
+                tofill[0].one_state.push_front(call_no_transition_internal);
+            }
+            template <class State>
+            static
+            typename ::boost::disable_if<
+                typename ::boost::is_same<State,Fsm>::type
+            ,void>::type
+            execute(boost::msm::wrap<State> const&,chain_row* tofill,boost::msm::back::dummy<1> = 0)
             {
                 typedef typename create_stt<Fsm>::type stt; 
                 BOOST_STATIC_CONSTANT(int, state_id = (get_state_id<stt,State>::value));
                 cell call_no_transition = &call_submachine< State >;
-                tofill[state_id].one_state.push_front(call_no_transition);
+                tofill[state_id+1].one_state.push_front(call_no_transition);
             }
         };
         template <int some_dummy> struct helper<false,false,some_dummy> 
@@ -207,7 +247,7 @@
                 typedef typename create_stt<Fsm>::type stt; 
                 BOOST_STATIC_CONSTANT(int, state_id = (get_state_id<stt,State>::value));
                 cell call_no_transition = &Fsm::call_no_transition;
-                tofill[state_id].one_state.push_back(call_no_transition);
+                tofill[state_id+1].one_state.push_back(call_no_transition);
             }
         };
         template <class State>
@@ -238,7 +278,7 @@
             typedef typename create_stt<Fsm>::type stt; 
             BOOST_STATIC_CONSTANT(int, state_id = (get_state_id<stt,State>::value));
             cell call_no_transition = &Fsm::default_eventless_transition;
-            tofill_entries[state_id].one_state.push_back(call_no_transition);
+            tofill_entries[state_id+1].one_state.push_back(call_no_transition);
         }
 
         dispatch_table* self;
@@ -266,7 +306,7 @@
     static const dispatch_table instance;
 
  public: // data members
-     chain_row entries[max_state];
+     chain_row entries[max_state+1];
 };
 
 template <class Fsm,class Stt, class Event>
Modified: trunk/boost/msm/back/state_machine.hpp
==============================================================================
--- trunk/boost/msm/back/state_machine.hpp	(original)
+++ trunk/boost/msm/back/state_machine.hpp	2011-09-08 17:13:03 EDT (Thu, 08 Sep 2011)
@@ -815,6 +815,43 @@
         }
     };
     template<
+        typename ROW
+    >
+    struct internal_ <ROW,library_sm>
+    {
+        typedef library_sm current_state_type;
+        typedef library_sm next_state_type;
+        typedef typename ROW::Evt transition_event;
+
+        // if a guard condition is here, call it to check that the event is accepted
+        static bool check_guard(library_sm& fsm,transition_event const& evt)
+        {
+            if ( ROW::guard_call(fsm,evt,
+                fsm,
+                fsm,
+                fsm.m_substate_list) )
+                return true;
+            return false;
+        }
+        // Take the transition action and return the next state.
+        static HandledEnum execute(library_sm& fsm, int , int , transition_event const& evt)
+        {
+            if (!check_guard(fsm,evt))
+            {
+                // guard rejected the event, we stay in the current one
+                return HANDLED_GUARD_REJECT;
+            }
+
+            // then call the action method
+            HandledEnum res = ROW::action_call(fsm,evt,
+                fsm,
+                fsm,
+                fsm.m_substate_list);
+            return res;
+        }
+    };
+
+    template<
         typename ROW,
         typename StateType
     >
@@ -836,6 +873,26 @@
         }
     };
     template<
+        typename ROW
+    >
+    struct a_internal_ <ROW,library_sm>
+    {
+        typedef library_sm current_state_type;
+        typedef library_sm next_state_type;
+        typedef typename ROW::Evt transition_event;
+
+        // Take the transition action and return the next state.
+        static HandledEnum execute(library_sm& fsm, int, int, transition_event const& evt)
+        {
+            // then call the action method
+            HandledEnum res = ROW::action_call(fsm,evt,
+                fsm,
+                fsm,
+                fsm.m_substate_list);
+            return res;
+        }
+    };
+    template<
         typename ROW,
         typename StateType
     >
@@ -867,6 +924,36 @@
         }
     };
     template<
+        typename ROW
+    >
+    struct g_internal_ <ROW,library_sm>
+    {
+        typedef library_sm current_state_type;
+        typedef library_sm next_state_type;
+        typedef typename ROW::Evt transition_event;
+
+        // if a guard condition is here, call it to check that the event is accepted
+        static bool check_guard(library_sm& fsm,transition_event const& evt)
+        {
+            if ( ROW::guard_call(fsm,evt,
+                fsm,
+                fsm,
+                fsm.m_substate_list) )
+                return true;
+            return false;
+        }
+        // Take the transition action and return the next state.
+        static HandledEnum execute(library_sm& fsm, int, int, transition_event const& evt)
+        {
+            if (!check_guard(fsm,evt))
+            {
+                // guard rejected the event, we stay in the current one
+                return HANDLED_GUARD_REJECT;
+            }
+            return HANDLED_TRUE;
+        }
+    };
+    template<
         typename ROW,
         typename StateType
     >
@@ -880,6 +967,19 @@
             return HANDLED_TRUE;
         }
     };
+    template<
+        typename ROW
+    >
+    struct _internal_ <ROW,library_sm>
+    {
+        typedef library_sm current_state_type;
+        typedef library_sm next_state_type;
+        typedef typename ROW::Evt transition_event;
+        static HandledEnum execute(library_sm& , int , int , transition_event const& )
+        {
+            return HANDLED_TRUE;
+        }
+    };
     // Template used to form forwarding rows in the transition table for every row of a composite SM
     template<
         typename T1
@@ -1009,18 +1109,6 @@
         // first get the table of a composite
         typedef typename recursive_get_transition_table<StateType>::type original_table;
 
-        // add the internal events defined in the internal_transition_table
-        // Note: these are added first because they must have a lesser prio
-        // than the deeper transitions in the sub regions
-        typedef typename StateType::internal_transition_table istt_simulated;
-
-        // table made of a stt + internal transitions of composite
-        typedef typename ::boost::mpl::fold<
-            istt_simulated,::boost::mpl::vector0<>,
-            ::boost::mpl::push_back< ::boost::mpl::placeholders::_1,
-                                     make_row_tag< ::boost::mpl::placeholders::_2 , StateType> >
-        >::type intermediate;
-
         // we now look for the events the composite has in its internal transitions
         // the internal ones are searched recursively in sub-sub... states
         // we go recursively because our states can also have internal tables or substates etc.
@@ -1037,8 +1125,8 @@
         // and add for every event a forwarding row
         typedef typename ::boost::mpl::eval_if<
                 typename CompilePolicy::add_forwarding_rows,
-                add_forwarding_row_helper<table_with_all_events,intermediate,StateType>,
-                ::boost::mpl::identity<intermediate>
+                add_forwarding_row_helper<table_with_all_events,::boost::mpl::vector0<>,StateType>,
+                ::boost::mpl::identity< ::boost::mpl::vector0<> >
         >::type type;
     };
     template <class StateType>
@@ -1046,6 +1134,7 @@
     {
         typedef typename create_real_stt<StateType, typename StateType::internal_transition_table >::type type;
     };
+    // typedefs used internally
     typedef typename create_real_stt<Derived>::type real_transition_table;
     typedef typename create_stt<library_sm>::type stt;
     typedef typename get_initial_states<typename Derived::initial_state>::type initial_states;
@@ -1053,6 +1142,9 @@
     typedef typename HistoryPolicy::template apply<nr_regions::value>::type concrete_history;
 
     typedef typename ::boost::fusion::result_of::as_set<state_list>::type substate_list;
+    typedef typename ::boost::msm::back::generate_event_set<
+        typename create_real_stt<library_sm, typename library_sm::internal_transition_table >::type
+    >::type processable_events_internal_table;
 
     // extends the transition table with rows from composite states
     template <class Composite>
@@ -1061,9 +1153,27 @@
         // add the init states
         //typedef typename create_stt<Composite>::type stt;
         typedef typename Composite::stt Stt;
+
+        // add the internal events defined in the internal_transition_table
+        // Note: these are added first because they must have a lesser prio
+        // than the deeper transitions in the sub regions
+        // table made of a stt + internal transitions of composite
+        typedef typename ::boost::mpl::fold<
+            typename Composite::internal_transition_table,::boost::mpl::vector0<>,
+            ::boost::mpl::push_back< ::boost::mpl::placeholders::_1,
+                                     make_row_tag< ::boost::mpl::placeholders::_2 , Composite> >
+        >::type internal_stt;
+
+        typedef typename ::boost::mpl::insert_range<
+            Stt,
+            typename ::boost::mpl::end<Stt>::type,
+            internal_stt
+            //typename get_internal_transition_table<Composite, ::boost::mpl::true_ >::type
+        >::type stt_plus_internal;
+
         // for every state, add its transition table (if any)
         // transformed as frow
-        typedef typename ::boost::mpl::fold<state_list,Stt,
+        typedef typename ::boost::mpl::fold<state_list,stt_plus_internal,
                 ::boost::mpl::insert_range< 
                         ::boost::mpl::placeholders::_1, 
                         ::boost::mpl::end< ::boost::mpl::placeholders::_1>,
@@ -1731,6 +1841,35 @@
         bool        handled;
     };
 
+    // helper class called in case the event to process has been found in the fsm's internal stt and is therefore processable
+    template<class Event>
+    struct process_fsm_internal_table
+    {
+        typedef typename ::boost::mpl::has_key<processable_events_internal_table,Event>::type is_event_processable;
+
+        // forward to the correct do_process
+        static void process(Event const& evt,library_sm* self_,HandledEnum& result)
+        {
+            do_process(evt,self_,result,is_event_processable());
+        }
+    private:
+        // the event is processable, let's try!
+        static void do_process(Event const& evt,library_sm* self_,HandledEnum& result, ::boost::mpl::true_)
+        {
+            if (result != HANDLED_TRUE)
+            {
+                typedef dispatch_table<library_sm,complete_table,Event,CompilePolicy> table;
+                HandledEnum res_internal = table::instance.entries[0](*self_, 0, self_->m_states[0], evt);
+                result = (HandledEnum)((int)result | (int)res_internal);
+            }
+        }
+        // version doing nothing if the event is not in the internal stt and we can save ourselves the time trying to process
+        static void do_process(Event const& ,library_sm* ,HandledEnum& , ::boost::mpl::false_)
+        {
+            // do nothing
+        }
+    };
+
     template <class StateType,class Enable=void>
     struct region_processing_helper 
     {
@@ -1742,10 +1881,13 @@
         {
             // use this table as if it came directly from the user
             typedef dispatch_table<library_sm,complete_table,Event,CompilePolicy> table;
+            // +1 because index 0 is reserved for this fsm
             HandledEnum res =
-                table::instance.entries[self->m_states[0]](
+                table::instance.entries[self->m_states[0]+1](
                 *self, 0, self->m_states[0], evt);
             result = (HandledEnum)((int)result | (int)res);
+            // process the event in the internal table of this fsm if the event is processable (present in the table)
+            process_fsm_internal_table<Event>::process(evt,self,result);
         }
         library_sm*     self;
         HandledEnum&    result;
@@ -1765,8 +1907,9 @@
             {
                 // use this table as if it came directly from the user
                 typedef dispatch_table<library_sm,complete_table,Event,CompilePolicy> table;
+                // +1 because index 0 is reserved for this fsm
                 HandledEnum res =
-                    table::instance.entries[self_->m_states[region_id::value]](
+                    table::instance.entries[self_->m_states[region_id::value]+1](
                     *self_, region_id::value , self_->m_states[region_id::value], evt);
                 result_ = (HandledEnum)((int)result_ | (int)res);
                 In< ::boost::mpl::int_<region_id::value+1> >::process(evt,self_,result_);
@@ -1777,7 +1920,11 @@
         {
             // end of processing
             template<class Event>
-            static void process(Event const& ,library_sm*,HandledEnum&){}
+            static void process(Event const& evt,library_sm* self_,HandledEnum& result_)
+            {
+                // process the event in the internal table of this fsm if the event is processable (present in the table)
+                process_fsm_internal_table<Event>::process(evt,self_,result_);
+            }
         };
         public:
         region_processing_helper(library_sm* self_,HandledEnum& result_)
@@ -1785,8 +1932,6 @@
         template<class Event>
         void process(Event const& evt)
         {
-            // use this table as if it came directly from the user
-            typedef dispatch_table<library_sm,complete_table,Event,CompilePolicy> table;
             In< ::boost::mpl::int_<0> >::process(evt,self,result);
         }
 
@@ -2421,6 +2566,14 @@
     {
         return HANDLED_FALSE;
     }
+    // no transition for event for internal transitions (not an error).
+    template <class Event>
+    static HandledEnum call_no_transition_internal(library_sm& , int , int , Event const& )
+    {
+        //// reject to give others a chance to handle
+        //return HANDLED_GUARD_REJECT;
+        return HANDLED_FALSE;
+    }
     // called for deferred events. Address set in the dispatch_table at init
     template <class Event>
     static HandledEnum defer_transition(library_sm& fsm, int , int , Event const& e)