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