File indexing completed on 2025-06-30 08:20:41
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