Boost logo

Boost-Commit :

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)


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