File indexing completed on 2025-11-04 09:53:17
0001 
0002 
0003 
0004 
0005 
0006 
0007 
0008 
0009 
0010 
0011 #ifndef BOOST_MSM_BACK_DISPATCH_TABLE_H
0012 #define BOOST_MSM_BACK_DISPATCH_TABLE_H
0013 
0014 #include <cstdint>
0015 #include <utility>
0016 
0017 #include <boost/mpl/reverse_fold.hpp>
0018 #include <boost/mpl/greater.hpp>
0019 #include <boost/mpl/filter_view.hpp>
0020 #include <boost/mpl/pop_front.hpp>
0021 #include <boost/mpl/for_each.hpp>
0022 #include <boost/mpl/advance.hpp>
0023 
0024 #include <boost/type_traits/is_base_of.hpp>
0025 #include <boost/type_traits/is_same.hpp>
0026 
0027 #include <boost/msm/event_traits.hpp>
0028 #include <boost/msm/back/metafunctions.hpp>
0029 #include <boost/msm/back/common_types.hpp>
0030 
0031 BOOST_MPL_HAS_XXX_TRAIT_DEF(is_frow)
0032 
0033 namespace boost { namespace msm { namespace back 
0034 {
0035 
0036 
0037 
0038 
0039 template <class Fsm,class Stt, class Event,class CompilePolicy>
0040 struct dispatch_table
0041 {
0042  private:
0043     
0044     typedef HandledEnum (*cell)(Fsm&, int,int,Event const&);
0045     typedef bool (*guard)(Fsm&, Event const&);
0046 
0047     
0048     
0049     template< typename Seq,typename AnEvent,typename State >
0050     struct chain_row
0051     {
0052         typedef State   current_state_type;
0053         typedef AnEvent transition_event;
0054 
0055         
0056         struct execute_helper
0057         {
0058             template <class Sequence>
0059             static
0060             HandledEnum
0061             execute(Fsm& , int, int, Event& , ::boost::mpl::true_ const & )
0062             {
0063                 
0064                 return HANDLED_FALSE;
0065             }
0066 
0067             template <class Sequence>
0068             static
0069             HandledEnum
0070             execute(Fsm& fsm, int region_index , int state, Event& evt,
0071                     ::boost::mpl::false_ const & )
0072             {
0073                  
0074                  typedef typename ::boost::mpl::front<Sequence>::type first_row;
0075                  HandledEnum res = first_row::execute(fsm,region_index,state,evt);
0076                  if (HANDLED_TRUE!=res && HANDLED_DEFERRED!=res)
0077                  {
0078                     
0079                     HandledEnum sub_res = 
0080                          execute<typename ::boost::mpl::pop_front<Sequence>::type>(fsm,region_index,state,evt,
0081                             ::boost::mpl::bool_<
0082                                 ::boost::mpl::empty<typename ::boost::mpl::pop_front<Sequence>::type>::type::value>());
0083                     
0084                     if ((HANDLED_FALSE==sub_res) && (HANDLED_GUARD_REJECT==res) )
0085                         return HANDLED_GUARD_REJECT;
0086                     else
0087                         return sub_res;
0088                  }
0089                  return res;
0090             }
0091         };
0092         
0093         static HandledEnum execute(Fsm& fsm, int region_index, int state, Event& evt)
0094         {
0095             
0096             return execute_helper::template execute<Seq>(fsm,region_index,state,evt,
0097                 ::boost::mpl::bool_< ::boost::mpl::empty<Seq>::type::value>());
0098         }
0099     };
0100     
0101     template< typename Entry > 
0102     struct make_chain_row_from_map_entry
0103     { 
0104         
0105         
0106         enum {number_frows = ::boost::mpl::count_if< typename Entry::second,has_is_frow< ::boost::mpl::placeholders::_1> >::value};
0107 
0108         
0109         template<class Sequence, int NumberToDelete>
0110         struct erase_first_rows
0111         {
0112             typedef typename ::boost::mpl::erase<
0113                 typename Entry::second,
0114                 typename ::boost::mpl::begin<Sequence>::type,
0115                 typename ::boost::mpl::advance<
0116                         typename ::boost::mpl::begin<Sequence>::type, 
0117                         ::boost::mpl::int_<NumberToDelete> >::type
0118             >::type type;
0119         };
0120         
0121         typedef typename ::boost::mpl::eval_if<
0122             typename ::boost::mpl::bool_< number_frows >= 2 >::type,
0123             erase_first_rows<typename Entry::second,number_frows-1>,
0124             ::boost::mpl::identity<typename Entry::second>
0125         >::type filtered_stt;
0126 
0127         typedef chain_row<filtered_stt,Event,
0128             typename Entry::first > type;
0129     }; 
0130     
0131     template <class Transition,class NewEvent>
0132     struct replace_event
0133     {
0134         typedef typename Transition::template replace_event<NewEvent>::type type;
0135     };
0136     
0137     
0138     template <class FrowTransition>
0139     struct change_frow_event
0140     {
0141         typedef typename ::boost::mpl::eval_if<
0142             typename has_is_frow<FrowTransition>::type,
0143             replace_event<FrowTransition,Event>,
0144             boost::mpl::identity<FrowTransition>
0145         >::type type;
0146     };
0147     
0148     
0149     typedef typename generate_state_set<Stt>::type state_list;
0150     BOOST_STATIC_CONSTANT(int, max_state = ( ::boost::mpl::size<state_list>::value));
0151 
0152     template <class Transition>
0153     struct convert_event_and_forward
0154     {
0155         static HandledEnum execute(Fsm& fsm, int region_index, int state, Event const& evt)
0156         {
0157             typename Transition::transition_event forwarded(evt);
0158             return Transition::execute(fsm,region_index,state,forwarded);
0159         }
0160     };
0161 
0162     
0163     
0164     struct init_cell
0165     {
0166         init_cell(dispatch_table* self_)
0167           : self(self_)
0168         {}
0169         
0170         
0171         template <class Transition>
0172         typename ::boost::disable_if<
0173             typename ::boost::is_same<typename Transition::current_state_type,Fsm>::type
0174         ,void>::type
0175         init_event_base_case(Transition const&, ::boost::mpl::true_ const &, ::boost::mpl::false_ const &) const
0176         {
0177             typedef typename create_stt<Fsm>::type stt; 
0178             BOOST_STATIC_CONSTANT(int, state_id = 
0179                 (get_state_id<stt,typename Transition::current_state_type>::value));
0180             
0181             self->entries[state_id + 1] = reinterpret_cast<cell>(
0182                 reinterpret_cast<std::uintptr_t>(&Transition::execute));
0183         }
0184         template <class Transition>
0185         typename ::boost::enable_if<
0186             typename ::boost::is_same<typename Transition::current_state_type,Fsm>::type
0187         ,void>::type
0188         init_event_base_case(Transition const&, ::boost::mpl::true_ const &, ::boost::mpl::false_ const &) const
0189         {
0190             self->entries[0] = reinterpret_cast<cell>(&Transition::execute);
0191         }
0192 
0193         
0194         
0195         template <class Transition>
0196         typename ::boost::disable_if<
0197             typename ::boost::is_same<typename Transition::current_state_type,Fsm>::type
0198         ,void>::type
0199         init_event_base_case(Transition const&, ::boost::mpl::false_ const &, ::boost::mpl::true_ const &) const
0200         {
0201             typedef typename create_stt<Fsm>::type stt; 
0202             BOOST_STATIC_CONSTANT(int, state_id = 
0203                 (get_state_id<stt,typename Transition::current_state_type>::value));
0204             self->entries[state_id+1] = &convert_event_and_forward<Transition>::execute;
0205         }
0206         template <class Transition>
0207         typename ::boost::enable_if<
0208             typename ::boost::is_same<typename Transition::current_state_type,Fsm>::type
0209         ,void>::type
0210         init_event_base_case(Transition const&, ::boost::mpl::false_ const &, ::boost::mpl::true_ const &) const
0211         {
0212             self->entries[0] = &convert_event_and_forward<Transition>::execute;
0213         }
0214         template <class Transition>
0215         typename ::boost::disable_if<
0216             typename ::boost::is_same<typename Transition::current_state_type,Fsm>::type
0217         ,void>::type
0218         init_event_base_case(Transition const&, ::boost::mpl::true_ const &, ::boost::mpl::true_ const &) const
0219         {
0220             typedef typename create_stt<Fsm>::type stt;
0221             BOOST_STATIC_CONSTANT(int, state_id =
0222                 (get_state_id<stt,typename Transition::current_state_type>::value));
0223             self->entries[state_id+1] = &convert_event_and_forward<Transition>::execute;
0224         }
0225         template <class Transition>
0226         typename ::boost::enable_if<
0227             typename ::boost::is_same<typename Transition::current_state_type,Fsm>::type
0228         ,void>::type
0229         init_event_base_case(Transition const&, ::boost::mpl::true_ const &, ::boost::mpl::true_ const &) const
0230         {
0231             self->entries[0] = &convert_event_and_forward<Transition>::execute;
0232         }
0233         
0234 
0235         
0236         
0237         template <class Transition>
0238         typename ::boost::disable_if<
0239             typename ::boost::is_same<typename Transition::current_state_type,Fsm>::type
0240         ,void>::type
0241         init_event_base_case(Transition const&, ::boost::mpl::false_ const &, ::boost::mpl::false_ const &) const
0242         {
0243             typedef typename create_stt<Fsm>::type stt; 
0244             BOOST_STATIC_CONSTANT(int, state_id = 
0245                 (get_state_id<stt,typename Transition::current_state_type>::value));
0246             self->entries[state_id+1] = &Transition::execute;
0247         }
0248         template <class Transition>
0249         typename ::boost::enable_if<
0250             typename ::boost::is_same<typename Transition::current_state_type,Fsm>::type
0251         ,void>::type
0252         init_event_base_case(Transition const&, ::boost::mpl::false_ const &, ::boost::mpl::false_ const &) const
0253         {
0254             self->entries[0] = &Transition::execute;
0255         }
0256         
0257         template <class Transition>
0258         typename ::boost::enable_if<typename has_not_real_row_tag<Transition>::type,void >::type
0259             operator()(Transition const&,boost::msm::back::dummy<0> = 0) const
0260         {
0261             
0262         }
0263         template <class Transition>
0264         typename ::boost::disable_if<typename has_not_real_row_tag<Transition>::type,void >::type
0265         operator()(Transition const& tr,boost::msm::back::dummy<1> = 0) const
0266         {
0267             
0268             init_event_base_case(tr,
0269                 ::boost::mpl::bool_< 
0270                     ::boost::is_base_of<typename Transition::transition_event,Event>::type::value>(),
0271                 ::boost::mpl::bool_< 
0272                     ::boost::msm::is_kleene_event<typename Transition::transition_event>::type::value>());
0273         }
0274     
0275         dispatch_table* self;
0276     };
0277 
0278     
0279     
0280     
0281     template <class EventType,class Enable=void>
0282     struct default_init_cell
0283     {
0284         default_init_cell(dispatch_table* self_,cell* tofill_entries_)
0285             : self(self_),tofill_entries(tofill_entries_)
0286         {}
0287         template <class State>
0288         typename ::boost::enable_if<typename has_state_delayed_event<State,Event>::type,void>::type
0289         operator()(boost::msm::wrap<State> const&,boost::msm::back::dummy<0> = 0)
0290         {
0291             typedef typename create_stt<Fsm>::type stt; 
0292             BOOST_STATIC_CONSTANT(int, state_id = (get_state_id<stt,State>::value));
0293             cell call_no_transition = &Fsm::defer_transition;
0294             tofill_entries[state_id+1] = call_no_transition;
0295         }
0296         template <class State>
0297         typename ::boost::disable_if<
0298             typename ::boost::mpl::or_<
0299                 typename has_state_delayed_event<State,Event>::type,
0300                 typename ::boost::is_same<State,Fsm>::type
0301             >::type
0302         ,void >::type
0303         operator()(boost::msm::wrap<State> const&,boost::msm::back::dummy<1> = 0)
0304         {
0305             typedef typename create_stt<Fsm>::type stt; 
0306             BOOST_STATIC_CONSTANT(int, state_id = (get_state_id<stt,State>::value));
0307             cell call_no_transition = &Fsm::call_no_transition;
0308             tofill_entries[state_id+1] = call_no_transition;
0309         }
0310         
0311         template <class State>
0312         typename ::boost::enable_if<
0313             typename ::boost::mpl::and_<
0314                 typename ::boost::mpl::not_<typename has_state_delayed_event<State,Event>::type>::type,
0315                 typename ::boost::is_same<State,Fsm>::type
0316             >::type
0317         ,void>::type
0318         operator()(boost::msm::wrap<State> const&,boost::msm::back::dummy<2> = 0)
0319         {
0320             cell call_no_transition = &Fsm::call_no_transition_internal;
0321             tofill_entries[0] = call_no_transition;
0322         }
0323         dispatch_table* self;
0324         cell* tofill_entries;
0325     };
0326 
0327     
0328     template <class EventType>
0329     struct default_init_cell<EventType,
0330                              typename ::boost::enable_if<
0331                                 typename is_completion_event<EventType>::type>::type>
0332     {
0333         default_init_cell(dispatch_table* self_,cell* tofill_entries_)
0334             : self(self_),tofill_entries(tofill_entries_)
0335         {}
0336 
0337         
0338         
0339         
0340         template <class State>
0341         typename ::boost::disable_if<
0342             typename ::boost::is_same<State,Fsm>::type
0343         ,void>::type
0344         operator()(boost::msm::wrap<State> const&,boost::msm::back::dummy<0> = 0)
0345         {
0346             typedef typename create_stt<Fsm>::type stt; 
0347             BOOST_STATIC_CONSTANT(int, state_id = (get_state_id<stt,State>::value));
0348             cell call_no_transition = &Fsm::default_eventless_transition;
0349             tofill_entries[state_id+1] = call_no_transition;
0350         }
0351 
0352         template <class State>
0353         typename ::boost::enable_if<
0354             typename ::boost::is_same<State,Fsm>::type
0355         ,void>::type
0356         operator()(boost::msm::wrap<State> const&,boost::msm::back::dummy<1> = 0)
0357         {
0358             cell call_no_transition = &Fsm::default_eventless_transition;
0359             tofill_entries[0] = call_no_transition;
0360         }
0361         dispatch_table* self;
0362         cell* tofill_entries;
0363     };
0364 
0365  public:
0366     
0367     dispatch_table()
0368     {
0369         
0370         ::boost::mpl::for_each<typename generate_state_set<Stt>::type, 
0371                                boost::msm::wrap< ::boost::mpl::placeholders::_1> >
0372                         (default_init_cell<Event>(this,entries));
0373 
0374         
0375         
0376         
0377         typedef typename ::boost::mpl::reverse_fold<
0378                         
0379                         ::boost::mpl::filter_view
0380                             <Stt, boost::mpl::or_<
0381                                     ::boost::is_base_of<transition_event< ::boost::mpl::placeholders::_>, Event>,
0382                                     ::boost::msm::is_kleene_event<transition_event< ::boost::mpl::placeholders::_> >
0383                                     >
0384                             >,
0385                         
0386                         ::boost::mpl::map<>,
0387                         ::boost::mpl::if_<
0388                             
0389                             ::boost::mpl::has_key< ::boost::mpl::placeholders::_1,
0390                                                    transition_source_type< ::boost::mpl::placeholders::_2> >,
0391                             
0392                             ::boost::mpl::insert< 
0393                                 ::boost::mpl::placeholders::_1,
0394                                 ::boost::mpl::pair<transition_source_type< ::boost::mpl::placeholders::_2>,
0395                                                    ::boost::mpl::push_back< 
0396                                                         ::boost::mpl::at< ::boost::mpl::placeholders::_1,
0397                                                         transition_source_type< ::boost::mpl::placeholders::_2> >,
0398                                                         change_frow_event< ::boost::mpl::placeholders::_2 > > 
0399                                                    > >,
0400                             
0401                             ::boost::mpl::insert< 
0402                                         ::boost::mpl::placeholders::_1,
0403                                         ::boost::mpl::pair<transition_source_type< ::boost::mpl::placeholders::_2>,
0404                                         make_vector< change_frow_event< ::boost::mpl::placeholders::_2> > > >
0405                                >
0406                        >::type map_of_row_seq;
0407         
0408         typedef typename ::boost::mpl::fold<
0409             map_of_row_seq,::boost::mpl::vector0<>,
0410             ::boost::mpl::if_<
0411                      ::boost::mpl::greater< ::boost::mpl::size< 
0412                                                     ::boost::mpl::second< ::boost::mpl::placeholders::_2> >,
0413                                             ::boost::mpl::int_<1> >,
0414                      
0415                      ::boost::mpl::push_back< ::boost::mpl::placeholders::_1, 
0416                                     make_chain_row_from_map_entry< ::boost::mpl::placeholders::_2> >,
0417                      
0418                      ::boost::mpl::push_back< ::boost::mpl::placeholders::_1, 
0419                                               get_first_element_pair_second< ::boost::mpl::placeholders::_2> > 
0420              > >::type chained_rows; 
0421         
0422         ::boost::mpl::for_each<chained_rows>(init_cell(this));
0423     }
0424 
0425     
0426     static const dispatch_table& instance() {
0427         static dispatch_table table;
0428         return table;
0429     }
0430 
0431  public: 
0432      
0433     cell entries[max_state+1];
0434 };
0435 
0436 }}} 
0437 
0438 
0439 #endif 
0440