File indexing completed on 2025-07-01 08:21:36
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_MSM_BACK_STATEMACHINE_H
0012 #define BOOST_MSM_BACK_STATEMACHINE_H
0013
0014 #include <exception>
0015 #include <vector>
0016 #include <functional>
0017 #include <numeric>
0018 #include <utility>
0019 #include <algorithm>
0020
0021 #include <boost/core/no_exceptions_support.hpp>
0022
0023 #include <boost/core/ignore_unused.hpp>
0024 #include <boost/mpl/contains.hpp>
0025 #include <boost/mpl/deref.hpp>
0026 #include <boost/mpl/assert.hpp>
0027
0028 #include <boost/fusion/container/vector/convert.hpp>
0029 #include <boost/fusion/include/as_vector.hpp>
0030 #include <boost/fusion/include/as_set.hpp>
0031 #include <boost/fusion/container/set.hpp>
0032 #include <boost/fusion/include/set.hpp>
0033 #include <boost/fusion/include/set_fwd.hpp>
0034 #include <boost/fusion/include/mpl.hpp>
0035 #include <boost/fusion/sequence/intrinsic/at_key.hpp>
0036 #include <boost/fusion/include/at_key.hpp>
0037 #include <boost/fusion/algorithm/iteration/for_each.hpp>
0038 #include <boost/fusion/include/for_each.hpp>
0039
0040 #include <boost/assert.hpp>
0041 #include <boost/ref.hpp>
0042 #include <boost/type_traits.hpp>
0043 #include <boost/utility/enable_if.hpp>
0044 #include <boost/type_traits/is_convertible.hpp>
0045
0046 #include <boost/bind/bind.hpp>
0047 #include <boost/function.hpp>
0048 #ifndef BOOST_NO_RTTI
0049 #include <boost/any.hpp>
0050 #endif
0051
0052 #include <boost/serialization/base_object.hpp>
0053
0054 #include <boost/parameter.hpp>
0055
0056 #include <boost/msm/active_state_switching_policies.hpp>
0057 #include <boost/msm/row_tags.hpp>
0058 #include <boost/msm/msm_grammar.hpp>
0059 #include <boost/msm/back/fold_to_list.hpp>
0060 #include <boost/msm/back/metafunctions.hpp>
0061 #include <boost/msm/back/history_policies.hpp>
0062 #include <boost/msm/back/common_types.hpp>
0063 #include <boost/msm/back/args.hpp>
0064 #include <boost/msm/back/default_compile_policy.hpp>
0065 #include <boost/msm/back/dispatch_table.hpp>
0066 #include <boost/msm/back/no_fsm_check.hpp>
0067 #include <boost/msm/back/queue_container_deque.hpp>
0068
0069 BOOST_MPL_HAS_XXX_TRAIT_DEF(accept_sig)
0070 BOOST_MPL_HAS_XXX_TRAIT_DEF(no_automatic_create)
0071 BOOST_MPL_HAS_XXX_TRAIT_DEF(non_forwarding_flag)
0072 BOOST_MPL_HAS_XXX_TRAIT_DEF(direct_entry)
0073 BOOST_MPL_HAS_XXX_TRAIT_DEF(initial_event)
0074 BOOST_MPL_HAS_XXX_TRAIT_DEF(final_event)
0075 BOOST_MPL_HAS_XXX_TRAIT_DEF(do_serialize)
0076 BOOST_MPL_HAS_XXX_TRAIT_DEF(history_policy)
0077 BOOST_MPL_HAS_XXX_TRAIT_DEF(fsm_check)
0078 BOOST_MPL_HAS_XXX_TRAIT_DEF(compile_policy)
0079 BOOST_MPL_HAS_XXX_TRAIT_DEF(queue_container_policy)
0080 BOOST_MPL_HAS_XXX_TRAIT_DEF(using_declared_table)
0081 BOOST_MPL_HAS_XXX_TRAIT_DEF(event_queue_before_deferred_queue)
0082
0083 #ifndef BOOST_MSM_CONSTRUCTOR_ARG_SIZE
0084 #define BOOST_MSM_CONSTRUCTOR_ARG_SIZE 5
0085 #endif
0086
0087 namespace boost { namespace msm { namespace back
0088 {
0089
0090 template <class StateType,class Event>
0091 struct direct_entry_event
0092 {
0093 typedef int direct_entry;
0094 typedef StateType active_state;
0095 typedef Event contained_event;
0096
0097 direct_entry_event(Event const& evt):m_event(evt){}
0098 Event const& m_event;
0099 };
0100
0101 BOOST_PARAMETER_TEMPLATE_KEYWORD(front_end)
0102 BOOST_PARAMETER_TEMPLATE_KEYWORD(history_policy)
0103 BOOST_PARAMETER_TEMPLATE_KEYWORD(compile_policy)
0104 BOOST_PARAMETER_TEMPLATE_KEYWORD(fsm_check_policy)
0105 BOOST_PARAMETER_TEMPLATE_KEYWORD(queue_container_policy)
0106
0107 typedef ::boost::parameter::parameters<
0108 ::boost::parameter::required< ::boost::msm::back::tag::front_end >
0109 , ::boost::parameter::optional<
0110 ::boost::parameter::deduced< ::boost::msm::back::tag::history_policy>, has_history_policy< ::boost::mpl::_ >
0111 >
0112 , ::boost::parameter::optional<
0113 ::boost::parameter::deduced< ::boost::msm::back::tag::compile_policy>, has_compile_policy< ::boost::mpl::_ >
0114 >
0115 , ::boost::parameter::optional<
0116 ::boost::parameter::deduced< ::boost::msm::back::tag::fsm_check_policy>, has_fsm_check< ::boost::mpl::_ >
0117 >
0118 , ::boost::parameter::optional<
0119 ::boost::parameter::deduced< ::boost::msm::back::tag::queue_container_policy>,
0120 has_queue_container_policy< ::boost::mpl::_ >
0121 >
0122 > state_machine_signature;
0123
0124
0125 template <class T, class F,class Enable=void>
0126 struct make_euml_terminal;
0127 template <class T,class F>
0128 struct make_euml_terminal<T,F,typename ::boost::disable_if<has_using_declared_table<F> >::type>
0129 {};
0130 template <class T,class F>
0131 struct make_euml_terminal<T,F,typename ::boost::enable_if<has_using_declared_table<F> >::type>
0132 : public proto::extends<typename proto::terminal< boost::msm::state_tag>::type, T, boost::msm::state_domain>
0133 {};
0134
0135
0136
0137
0138 template <
0139 class A0
0140 , class A1 = parameter::void_
0141 , class A2 = parameter::void_
0142 , class A3 = parameter::void_
0143 , class A4 = parameter::void_
0144 >
0145 class state_machine :
0146 public ::boost::parameter::binding<
0147 typename state_machine_signature::bind<A0,A1,A2,A3,A4>::type, ::boost::msm::back::tag::front_end
0148 >::type
0149 , public make_euml_terminal<state_machine<A0,A1,A2,A3,A4>,
0150 typename ::boost::parameter::binding<
0151 typename state_machine_signature::bind<A0,A1,A2,A3,A4>::type, ::boost::msm::back::tag::front_end
0152 >::type
0153 >
0154 {
0155 public:
0156
0157 typedef typename
0158 state_machine_signature::bind<A0,A1,A2,A3,A4>::type
0159 state_machine_args;
0160
0161
0162 typedef typename ::boost::parameter::binding<
0163 state_machine_args, ::boost::msm::back::tag::front_end>::type Derived;
0164
0165 typedef typename ::boost::parameter::binding<
0166 state_machine_args, ::boost::msm::back::tag::history_policy, NoHistory >::type HistoryPolicy;
0167
0168 typedef typename ::boost::parameter::binding<
0169 state_machine_args, ::boost::msm::back::tag::compile_policy, favor_runtime_speed >::type CompilePolicy;
0170
0171 typedef typename ::boost::parameter::binding<
0172 state_machine_args, ::boost::msm::back::tag::fsm_check_policy, no_fsm_check >::type FsmCheckPolicy;
0173
0174 typedef typename ::boost::parameter::binding<
0175 state_machine_args, ::boost::msm::back::tag::queue_container_policy,
0176 queue_container_deque >::type QueueContainerPolicy;
0177
0178 private:
0179
0180 typedef boost::msm::back::state_machine<
0181 A0,A1,A2,A3,A4> library_sm;
0182
0183 typedef ::boost::function<
0184 execute_return ()> transition_fct;
0185 typedef ::boost::function<
0186 execute_return () > deferred_fct;
0187 typedef typename QueueContainerPolicy::
0188 template In<
0189 std::pair<deferred_fct,char> >::type deferred_events_queue_t;
0190 typedef typename QueueContainerPolicy::
0191 template In<transition_fct>::type events_queue_t;
0192
0193 typedef typename boost::mpl::eval_if<
0194 typename is_active_state_switch_policy<Derived>::type,
0195 get_active_state_switch_policy<Derived>,
0196
0197 ::boost::mpl::identity<active_state_switch_after_entry>
0198 >::type active_state_switching;
0199
0200 typedef bool (*flag_handler)(library_sm const&);
0201
0202
0203 template <class ,class , class, class, class
0204 > friend class boost::msm::back::state_machine;
0205
0206
0207
0208 template <class StateType,class Enable=void>
0209 struct visitor_fct_helper
0210 {
0211 public:
0212 visitor_fct_helper(){}
0213 void fill_visitors(int)
0214 {
0215 }
0216 template <class FCT>
0217 void insert(int,FCT)
0218 {
0219 }
0220 template <class VISITOR>
0221 void execute(int,VISITOR)
0222 {
0223 }
0224 };
0225
0226 template <class StateType>
0227 struct visitor_fct_helper<StateType,typename ::boost::enable_if<has_accept_sig<StateType> >::type>
0228 {
0229 public:
0230 visitor_fct_helper():m_state_visitors(){}
0231 void fill_visitors(int number_of_states)
0232 {
0233 m_state_visitors.resize(number_of_states);
0234 }
0235 template <class FCT>
0236 void insert(int index,FCT fct)
0237 {
0238 m_state_visitors[index]=fct;
0239 }
0240 void execute(int index)
0241 {
0242 m_state_visitors[index]();
0243 }
0244
0245 #define MSM_VISITOR_HELPER_EXECUTE_SUB(z, n, unused) ARG ## n vis ## n
0246 #define MSM_VISITOR_HELPER_EXECUTE(z, n, unused) \
0247 template <BOOST_PP_ENUM_PARAMS(n, class ARG)> \
0248 void execute(int index BOOST_PP_COMMA_IF(n) \
0249 BOOST_PP_ENUM(n, MSM_VISITOR_HELPER_EXECUTE_SUB, ~ ) ) \
0250 { \
0251 m_state_visitors[index](BOOST_PP_ENUM_PARAMS(n,vis)); \
0252 }
0253 BOOST_PP_REPEAT_FROM_TO(1,BOOST_PP_ADD(BOOST_MSM_VISITOR_ARG_SIZE,1), MSM_VISITOR_HELPER_EXECUTE, ~)
0254 #undef MSM_VISITOR_HELPER_EXECUTE
0255 #undef MSM_VISITOR_HELPER_EXECUTE_SUB
0256 private:
0257 typedef typename StateType::accept_sig::type visitor_fct;
0258 typedef std::vector<visitor_fct> visitors;
0259
0260 visitors m_state_visitors;
0261 };
0262
0263 template <class StateType,class Enable=int>
0264 struct deferred_msg_queue_helper
0265 {
0266 void clear(){}
0267 };
0268 template <class StateType>
0269 struct deferred_msg_queue_helper<StateType,
0270 typename ::boost::enable_if<
0271 typename ::boost::msm::back::has_fsm_deferred_events<StateType>::type,int >::type>
0272 {
0273 public:
0274 deferred_msg_queue_helper():m_deferred_events_queue(),m_cur_seq(0){}
0275 void clear()
0276 {
0277 m_deferred_events_queue.clear();
0278 }
0279 deferred_events_queue_t m_deferred_events_queue;
0280 char m_cur_seq;
0281 };
0282
0283 public:
0284
0285 typedef int composite_tag;
0286
0287
0288 typedef HistoryPolicy history_policy;
0289
0290 struct InitEvent { };
0291 struct ExitEvent { };
0292
0293 struct Flag_AND
0294 {
0295 typedef std::logical_and<bool> type;
0296 };
0297 struct Flag_OR
0298 {
0299 typedef std::logical_or<bool> type;
0300 };
0301 typedef typename Derived::BaseAllStates BaseState;
0302 typedef Derived ConcreteSM;
0303
0304
0305 typedef typename ::boost::mpl::eval_if<
0306 typename has_initial_event<Derived>::type,
0307 get_initial_event<Derived>,
0308 ::boost::mpl::identity<InitEvent>
0309 >::type fsm_initial_event;
0310
0311
0312 typedef typename ::boost::mpl::eval_if<
0313 typename has_final_event<Derived>::type,
0314 get_final_event<Derived>,
0315 ::boost::mpl::identity<ExitEvent>
0316 >::type fsm_final_event;
0317
0318 template <class ExitPoint>
0319 struct exit_pt : public ExitPoint
0320 {
0321
0322 typedef ExitPoint wrapped_exit;
0323 typedef int pseudo_exit;
0324 typedef library_sm owner;
0325 typedef int no_automatic_create;
0326 typedef typename
0327 ExitPoint::event Event;
0328 typedef ::boost::function<execute_return (Event const&)>
0329 forwarding_function;
0330
0331
0332 template <class ForwardEvent>
0333 void forward_event(ForwardEvent const& incomingEvent)
0334 {
0335
0336 ForwardHelper< ::boost::is_convertible<ForwardEvent,Event>::value>::helper(incomingEvent,m_forward);
0337 }
0338 void set_forward_fct(::boost::function<execute_return (Event const&)> fct)
0339 {
0340 m_forward = fct;
0341 }
0342 exit_pt():m_forward(){}
0343
0344 template <class RHS>
0345 exit_pt(RHS&):m_forward(){}
0346 exit_pt<ExitPoint>& operator= (const exit_pt<ExitPoint>& )
0347 {
0348 return *this;
0349 }
0350 private:
0351 forwarding_function m_forward;
0352
0353
0354 template <bool OwnEvent, int Dummy=0>
0355 struct ForwardHelper
0356 {
0357 template <class ForwardEvent>
0358 static void helper(ForwardEvent const& ,forwarding_function& )
0359 {
0360
0361 BOOST_ASSERT(false);
0362 }
0363 };
0364 template <int Dummy>
0365 struct ForwardHelper<true,Dummy>
0366 {
0367 template <class ForwardEvent>
0368 static void helper(ForwardEvent const& incomingEvent,forwarding_function& forward_fct)
0369 {
0370
0371 if (forward_fct)
0372 forward_fct(incomingEvent);
0373 }
0374 };
0375
0376 };
0377 template <class EntryPoint>
0378 struct entry_pt : public EntryPoint
0379 {
0380
0381 typedef EntryPoint wrapped_entry;
0382 typedef int pseudo_entry;
0383 typedef library_sm owner;
0384 typedef int no_automatic_create;
0385 };
0386 template <class EntryPoint>
0387 struct direct : public EntryPoint
0388 {
0389
0390 typedef EntryPoint wrapped_entry;
0391 typedef int explicit_entry_state;
0392 typedef library_sm owner;
0393 typedef int no_automatic_create;
0394 };
0395 typedef typename get_number_of_regions<typename Derived::initial_state>::type nr_regions;
0396
0397 template<
0398 typename ROW
0399 >
0400 struct row_
0401 {
0402
0403 typedef typename make_entry<typename ROW::Source,library_sm>::type T1;
0404 typedef typename make_exit<typename ROW::Target,library_sm>::type T2;
0405 typedef typename ROW::Evt transition_event;
0406
0407
0408
0409 typedef typename ::boost::mpl::eval_if<
0410 typename has_pseudo_exit<T1>::type,
0411 get_owner<T1,library_sm>,
0412 ::boost::mpl::identity<typename ROW::Source> >::type current_state_type;
0413
0414
0415
0416
0417 typedef typename ::boost::mpl::eval_if<
0418 typename ::boost::mpl::is_sequence<T2>::type,
0419 get_fork_owner<T2,library_sm>,
0420 ::boost::mpl::eval_if<
0421 typename has_no_automatic_create<T2>::type,
0422 get_owner<T2,library_sm>,
0423 ::boost::mpl::identity<T2> >
0424 >::type next_state_type;
0425
0426
0427 static bool check_guard(library_sm& fsm,transition_event const& evt)
0428 {
0429 if ( ROW::guard_call(fsm,evt,
0430 ::boost::fusion::at_key<current_state_type>(fsm.m_substate_list),
0431 ::boost::fusion::at_key<next_state_type>(fsm.m_substate_list),
0432 fsm.m_substate_list ) )
0433 return true;
0434 return false;
0435 }
0436
0437 static HandledEnum execute(library_sm& fsm, int region_index, int state, transition_event& evt)
0438 {
0439
0440 BOOST_STATIC_CONSTANT(int, current_state = (get_state_id<stt,current_state_type>::type::value));
0441 BOOST_STATIC_CONSTANT(int, next_state = (get_state_id<stt,next_state_type>::type::value));
0442 boost::ignore_unused(state);
0443 BOOST_ASSERT(state == (current_state));
0444
0445 if (has_pseudo_exit<T1>::type::value &&
0446 !is_exit_state_active<T1,get_owner<T1,library_sm> >(fsm))
0447 {
0448 return HANDLED_FALSE;
0449 }
0450 if (!check_guard(fsm,evt))
0451 {
0452
0453 return HANDLED_GUARD_REJECT;
0454 }
0455 fsm.m_states[region_index] = active_state_switching::after_guard(current_state,next_state);
0456
0457
0458 execute_exit<current_state_type>
0459 (::boost::fusion::at_key<current_state_type>(fsm.m_substate_list),evt,fsm);
0460 fsm.m_states[region_index] = active_state_switching::after_exit(current_state,next_state);
0461
0462
0463 HandledEnum res = ROW::action_call(fsm,evt,
0464 ::boost::fusion::at_key<current_state_type>(fsm.m_substate_list),
0465 ::boost::fusion::at_key<next_state_type>(fsm.m_substate_list),
0466 fsm.m_substate_list);
0467 fsm.m_states[region_index] = active_state_switching::after_action(current_state,next_state);
0468
0469
0470 convert_event_and_execute_entry<next_state_type,T2>
0471 (::boost::fusion::at_key<next_state_type>(fsm.m_substate_list),evt,fsm);
0472 fsm.m_states[region_index] = active_state_switching::after_entry(current_state,next_state);
0473 return res;
0474 }
0475 };
0476
0477
0478 template<
0479 typename ROW
0480 >
0481 struct g_row_
0482 {
0483
0484 typedef typename make_entry<typename ROW::Source,library_sm>::type T1;
0485 typedef typename make_exit<typename ROW::Target,library_sm>::type T2;
0486 typedef typename ROW::Evt transition_event;
0487
0488
0489
0490 typedef typename ::boost::mpl::eval_if<
0491 typename has_pseudo_exit<T1>::type,
0492 get_owner<T1,library_sm>,
0493 ::boost::mpl::identity<typename ROW::Source> >::type current_state_type;
0494
0495
0496
0497
0498 typedef typename ::boost::mpl::eval_if<
0499 typename ::boost::mpl::is_sequence<T2>::type,
0500 get_fork_owner<T2,library_sm>,
0501 ::boost::mpl::eval_if<
0502 typename has_no_automatic_create<T2>::type,
0503 get_owner<T2,library_sm>,
0504 ::boost::mpl::identity<T2> >
0505 >::type next_state_type;
0506
0507
0508 static bool check_guard(library_sm& fsm,transition_event const& evt)
0509 {
0510 if ( ROW::guard_call(fsm,evt,
0511 ::boost::fusion::at_key<current_state_type>(fsm.m_substate_list),
0512 ::boost::fusion::at_key<next_state_type>(fsm.m_substate_list),
0513 fsm.m_substate_list ))
0514 return true;
0515 return false;
0516 }
0517
0518 static HandledEnum execute(library_sm& fsm, int region_index, int state, transition_event const& evt)
0519 {
0520 BOOST_STATIC_CONSTANT(int, current_state = (get_state_id<stt,current_state_type>::type::value));
0521 BOOST_STATIC_CONSTANT(int, next_state = (get_state_id<stt,next_state_type>::type::value));
0522 boost::ignore_unused(state);
0523 BOOST_ASSERT(state == (current_state));
0524
0525 if (has_pseudo_exit<T1>::type::value &&
0526 !is_exit_state_active<T1,get_owner<T1,library_sm> >(fsm))
0527 {
0528 return HANDLED_FALSE;
0529 }
0530 if (!check_guard(fsm,evt))
0531 {
0532
0533 return HANDLED_GUARD_REJECT;
0534 }
0535 fsm.m_states[region_index] = active_state_switching::after_guard(current_state,next_state);
0536
0537
0538 execute_exit<current_state_type>
0539 (::boost::fusion::at_key<current_state_type>(fsm.m_substate_list),evt,fsm);
0540 fsm.m_states[region_index] = active_state_switching::after_exit(current_state,next_state);
0541 fsm.m_states[region_index] = active_state_switching::after_action(current_state,next_state);
0542
0543
0544 convert_event_and_execute_entry<next_state_type,T2>
0545 (::boost::fusion::at_key<next_state_type>(fsm.m_substate_list),evt,fsm);
0546 fsm.m_states[region_index] = active_state_switching::after_entry(current_state,next_state);
0547 return HANDLED_TRUE;
0548 }
0549 };
0550
0551
0552 template<
0553 typename ROW
0554 >
0555 struct a_row_
0556 {
0557
0558 typedef typename make_entry<typename ROW::Source,library_sm>::type T1;
0559 typedef typename make_exit<typename ROW::Target,library_sm>::type T2;
0560 typedef typename ROW::Evt transition_event;
0561
0562
0563
0564 typedef typename ::boost::mpl::eval_if<
0565 typename has_pseudo_exit<T1>::type,
0566 get_owner<T1,library_sm>,
0567 ::boost::mpl::identity<typename ROW::Source> >::type current_state_type;
0568
0569
0570
0571
0572 typedef typename ::boost::mpl::eval_if<
0573 typename ::boost::mpl::is_sequence<T2>::type,
0574 get_fork_owner<T2,library_sm>,
0575 ::boost::mpl::eval_if<
0576 typename has_no_automatic_create<T2>::type,
0577 get_owner<T2,library_sm>,
0578 ::boost::mpl::identity<T2> >
0579 >::type next_state_type;
0580
0581
0582 static HandledEnum execute(library_sm& fsm, int region_index, int state, transition_event& evt)
0583 {
0584 BOOST_STATIC_CONSTANT(int, current_state = (get_state_id<stt,current_state_type>::type::value));
0585 BOOST_STATIC_CONSTANT(int, next_state = (get_state_id<stt,next_state_type>::type::value));
0586 boost::ignore_unused(state);
0587 BOOST_ASSERT(state == (current_state));
0588
0589
0590 if (has_pseudo_exit<T1>::type::value &&
0591 !is_exit_state_active<T1,get_owner<T1,library_sm> >(fsm))
0592 {
0593 return HANDLED_FALSE;
0594 }
0595 fsm.m_states[region_index] = active_state_switching::after_guard(current_state,next_state);
0596
0597
0598
0599 execute_exit<current_state_type>
0600 (::boost::fusion::at_key<current_state_type>(fsm.m_substate_list),evt,fsm);
0601 fsm.m_states[region_index] = active_state_switching::after_exit(current_state,next_state);
0602
0603
0604 HandledEnum res = ROW::action_call(fsm,evt,
0605 ::boost::fusion::at_key<current_state_type>(fsm.m_substate_list),
0606 ::boost::fusion::at_key<next_state_type>(fsm.m_substate_list),
0607 fsm.m_substate_list);
0608 fsm.m_states[region_index] = active_state_switching::after_action(current_state,next_state);
0609
0610
0611 convert_event_and_execute_entry<next_state_type,T2>
0612 (::boost::fusion::at_key<next_state_type>(fsm.m_substate_list),evt,fsm);
0613 fsm.m_states[region_index] = active_state_switching::after_entry(current_state,next_state);
0614 return res;
0615 }
0616 };
0617
0618
0619 template<
0620 typename ROW
0621 >
0622 struct _row_
0623 {
0624
0625 typedef typename make_entry<typename ROW::Source,library_sm>::type T1;
0626 typedef typename make_exit<typename ROW::Target,library_sm>::type T2;
0627 typedef typename ROW::Evt transition_event;
0628
0629
0630
0631 typedef typename ::boost::mpl::eval_if<
0632 typename has_pseudo_exit<T1>::type,
0633 get_owner<T1,library_sm>,
0634 ::boost::mpl::identity<typename ROW::Source> >::type current_state_type;
0635
0636
0637
0638
0639 typedef typename ::boost::mpl::eval_if<
0640 typename ::boost::mpl::is_sequence<T2>::type,
0641 get_fork_owner<T2,library_sm>,
0642 ::boost::mpl::eval_if<
0643 typename has_no_automatic_create<T2>::type,
0644 get_owner<T2,library_sm>,
0645 ::boost::mpl::identity<T2> >
0646 >::type next_state_type;
0647
0648
0649 static HandledEnum execute(library_sm& fsm, int region_index, int state, transition_event const& evt)
0650 {
0651 BOOST_STATIC_CONSTANT(int, current_state = (get_state_id<stt,current_state_type>::type::value));
0652 BOOST_STATIC_CONSTANT(int, next_state = (get_state_id<stt,next_state_type>::type::value));
0653 boost::ignore_unused(state);
0654 BOOST_ASSERT(state == (current_state));
0655
0656
0657 if (has_pseudo_exit<T1>::type::value &&
0658 !is_exit_state_active<T1,get_owner<T1,library_sm> >(fsm))
0659 {
0660 return HANDLED_FALSE;
0661 }
0662 fsm.m_states[region_index] = active_state_switching::after_guard(current_state,next_state);
0663
0664
0665 execute_exit<current_state_type>
0666 (::boost::fusion::at_key<current_state_type>(fsm.m_substate_list),evt,fsm);
0667 fsm.m_states[region_index] = active_state_switching::after_exit(current_state,next_state);
0668 fsm.m_states[region_index] = active_state_switching::after_action(current_state,next_state);
0669
0670
0671
0672 convert_event_and_execute_entry<next_state_type,T2>
0673 (::boost::fusion::at_key<next_state_type>(fsm.m_substate_list),evt,fsm);
0674 fsm.m_states[region_index] = active_state_switching::after_entry(current_state,next_state);
0675 return HANDLED_TRUE;
0676 }
0677 };
0678
0679 template<
0680 typename ROW
0681 >
0682 struct irow_
0683 {
0684 typedef typename make_entry<typename ROW::Source,library_sm>::type T1;
0685 typedef typename make_exit<typename ROW::Target,library_sm>::type T2;
0686 typedef typename ROW::Evt transition_event;
0687 typedef typename ROW::Source current_state_type;
0688 typedef T2 next_state_type;
0689
0690
0691 static bool check_guard(library_sm& fsm,transition_event const& evt)
0692 {
0693 if ( ROW::guard_call(fsm,evt,
0694 ::boost::fusion::at_key<current_state_type>(fsm.m_substate_list),
0695 ::boost::fusion::at_key<next_state_type>(fsm.m_substate_list),
0696 fsm.m_substate_list))
0697 return true;
0698 return false;
0699 }
0700
0701 static HandledEnum execute(library_sm& fsm, int , int state, transition_event const& evt)
0702 {
0703
0704 BOOST_STATIC_CONSTANT(int, current_state = (get_state_id<stt,current_state_type>::type::value));
0705 boost::ignore_unused(state, current_state);
0706 BOOST_ASSERT(state == (current_state));
0707 if (!check_guard(fsm,evt))
0708 {
0709
0710 return HANDLED_GUARD_REJECT;
0711 }
0712
0713
0714 HandledEnum res = ROW::action_call(fsm,evt,
0715 ::boost::fusion::at_key<current_state_type>(fsm.m_substate_list),
0716 ::boost::fusion::at_key<next_state_type>(fsm.m_substate_list),
0717 fsm.m_substate_list);
0718 return res;
0719 }
0720 };
0721
0722
0723 template<
0724 typename ROW
0725 >
0726 struct g_irow_
0727 {
0728 typedef typename make_entry<typename ROW::Source,library_sm>::type T1;
0729 typedef typename make_exit<typename ROW::Target,library_sm>::type T2;
0730 typedef typename ROW::Evt transition_event;
0731 typedef typename ROW::Source current_state_type;
0732 typedef T2 next_state_type;
0733
0734
0735 static bool check_guard(library_sm& fsm,transition_event const& evt)
0736 {
0737 if ( ROW::guard_call(fsm,evt,
0738 ::boost::fusion::at_key<current_state_type>(fsm.m_substate_list),
0739 ::boost::fusion::at_key<next_state_type>(fsm.m_substate_list),
0740 fsm.m_substate_list) )
0741 return true;
0742 return false;
0743 }
0744
0745 static HandledEnum execute(library_sm& fsm, int , int state, transition_event const& evt)
0746 {
0747 BOOST_STATIC_CONSTANT(int, current_state = (get_state_id<stt,current_state_type>::type::value));
0748 boost::ignore_unused(state, current_state);
0749 BOOST_ASSERT(state == (current_state));
0750 if (!check_guard(fsm,evt))
0751 {
0752
0753 return HANDLED_GUARD_REJECT;
0754 }
0755 return HANDLED_TRUE;
0756 }
0757 };
0758
0759
0760 template<
0761 typename ROW
0762 >
0763 struct a_irow_
0764 {
0765 typedef typename make_entry<typename ROW::Source,library_sm>::type T1;
0766 typedef typename make_exit<typename ROW::Target,library_sm>::type T2;
0767
0768 typedef typename ROW::Evt transition_event;
0769 typedef typename ROW::Source current_state_type;
0770 typedef T2 next_state_type;
0771
0772
0773 static HandledEnum execute(library_sm& fsm, int , int state, transition_event const& evt)
0774 {
0775 BOOST_STATIC_CONSTANT(int, current_state = (get_state_id<stt,current_state_type>::type::value));
0776 boost::ignore_unused(state, current_state);
0777 BOOST_ASSERT(state == (current_state));
0778
0779
0780 HandledEnum res = ROW::action_call(fsm,evt,
0781 ::boost::fusion::at_key<current_state_type>(fsm.m_substate_list),
0782 ::boost::fusion::at_key<next_state_type>(fsm.m_substate_list),
0783 fsm.m_substate_list);
0784
0785 return res;
0786 }
0787 };
0788
0789 template<
0790 typename ROW
0791 >
0792 struct _irow_
0793 {
0794 typedef typename make_entry<typename ROW::Source,library_sm>::type T1;
0795 typedef typename make_exit<typename ROW::Target,library_sm>::type T2;
0796 typedef typename ROW::Evt transition_event;
0797 typedef typename ROW::Source current_state_type;
0798 typedef T2 next_state_type;
0799
0800
0801 static HandledEnum execute(library_sm& , int , int state, transition_event const& )
0802 {
0803 BOOST_STATIC_CONSTANT(int, current_state = (get_state_id<stt,current_state_type>::type::value));
0804 boost::ignore_unused(state, current_state);
0805 BOOST_ASSERT(state == (current_state));
0806 return HANDLED_TRUE;
0807 }
0808 };
0809
0810 template<
0811 typename ROW,
0812 typename StateType
0813 >
0814 struct internal_
0815 {
0816 typedef StateType current_state_type;
0817 typedef StateType next_state_type;
0818 typedef typename ROW::Evt transition_event;
0819
0820
0821 static bool check_guard(library_sm& fsm,transition_event const& evt)
0822 {
0823 if ( ROW::guard_call(fsm,evt,
0824 ::boost::fusion::at_key<StateType>(fsm.m_substate_list),
0825 ::boost::fusion::at_key<StateType>(fsm.m_substate_list),
0826 fsm.m_substate_list) )
0827 return true;
0828 return false;
0829 }
0830
0831 static HandledEnum execute(library_sm& fsm, int , int , transition_event const& evt)
0832 {
0833 if (!check_guard(fsm,evt))
0834 {
0835
0836 return HANDLED_GUARD_REJECT;
0837 }
0838
0839
0840 HandledEnum res = ROW::action_call(fsm,evt,
0841 ::boost::fusion::at_key<StateType>(fsm.m_substate_list),
0842 ::boost::fusion::at_key<StateType>(fsm.m_substate_list),
0843 fsm.m_substate_list);
0844 return res;
0845 }
0846 };
0847 template<
0848 typename ROW
0849 >
0850 struct internal_ <ROW,library_sm>
0851 {
0852 typedef library_sm current_state_type;
0853 typedef library_sm next_state_type;
0854 typedef typename ROW::Evt transition_event;
0855
0856
0857 static bool check_guard(library_sm& fsm,transition_event const& evt)
0858 {
0859 if ( ROW::guard_call(fsm,evt,
0860 fsm,
0861 fsm,
0862 fsm.m_substate_list) )
0863 return true;
0864 return false;
0865 }
0866
0867 static HandledEnum execute(library_sm& fsm, int , int , transition_event const& evt)
0868 {
0869 if (!check_guard(fsm,evt))
0870 {
0871
0872 return HANDLED_GUARD_REJECT;
0873 }
0874
0875
0876 HandledEnum res = ROW::action_call(fsm,evt,
0877 fsm,
0878 fsm,
0879 fsm.m_substate_list);
0880 return res;
0881 }
0882 };
0883
0884 template<
0885 typename ROW,
0886 typename StateType
0887 >
0888 struct a_internal_
0889 {
0890 typedef StateType current_state_type;
0891 typedef StateType next_state_type;
0892 typedef typename ROW::Evt transition_event;
0893
0894
0895 static HandledEnum execute(library_sm& fsm, int, int, transition_event const& evt)
0896 {
0897
0898 HandledEnum res = ROW::action_call(fsm,evt,
0899 ::boost::fusion::at_key<StateType>(fsm.m_substate_list),
0900 ::boost::fusion::at_key<StateType>(fsm.m_substate_list),
0901 fsm.m_substate_list);
0902 return res;
0903 }
0904 };
0905 template<
0906 typename ROW
0907 >
0908 struct a_internal_ <ROW,library_sm>
0909 {
0910 typedef library_sm current_state_type;
0911 typedef library_sm next_state_type;
0912 typedef typename ROW::Evt transition_event;
0913
0914
0915 static HandledEnum execute(library_sm& fsm, int, int, transition_event const& evt)
0916 {
0917
0918 HandledEnum res = ROW::action_call(fsm,evt,
0919 fsm,
0920 fsm,
0921 fsm.m_substate_list);
0922 return res;
0923 }
0924 };
0925 template<
0926 typename ROW,
0927 typename StateType
0928 >
0929 struct g_internal_
0930 {
0931 typedef StateType current_state_type;
0932 typedef StateType next_state_type;
0933 typedef typename ROW::Evt transition_event;
0934
0935
0936 static bool check_guard(library_sm& fsm,transition_event const& evt)
0937 {
0938 if ( ROW::guard_call(fsm,evt,
0939 ::boost::fusion::at_key<StateType>(fsm.m_substate_list),
0940 ::boost::fusion::at_key<StateType>(fsm.m_substate_list),
0941 fsm.m_substate_list) )
0942 return true;
0943 return false;
0944 }
0945
0946 static HandledEnum execute(library_sm& fsm, int, int, transition_event const& evt)
0947 {
0948 if (!check_guard(fsm,evt))
0949 {
0950
0951 return HANDLED_GUARD_REJECT;
0952 }
0953 return HANDLED_TRUE;
0954 }
0955 };
0956 template<
0957 typename ROW
0958 >
0959 struct g_internal_ <ROW,library_sm>
0960 {
0961 typedef library_sm current_state_type;
0962 typedef library_sm next_state_type;
0963 typedef typename ROW::Evt transition_event;
0964
0965
0966 static bool check_guard(library_sm& fsm,transition_event const& evt)
0967 {
0968 if ( ROW::guard_call(fsm,evt,
0969 fsm,
0970 fsm,
0971 fsm.m_substate_list) )
0972 return true;
0973 return false;
0974 }
0975
0976 static HandledEnum execute(library_sm& fsm, int, int, transition_event const& evt)
0977 {
0978 if (!check_guard(fsm,evt))
0979 {
0980
0981 return HANDLED_GUARD_REJECT;
0982 }
0983 return HANDLED_TRUE;
0984 }
0985 };
0986 template<
0987 typename ROW,
0988 typename StateType
0989 >
0990 struct _internal_
0991 {
0992 typedef StateType current_state_type;
0993 typedef StateType next_state_type;
0994 typedef typename ROW::Evt transition_event;
0995 static HandledEnum execute(library_sm& , int , int , transition_event const& )
0996 {
0997 return HANDLED_TRUE;
0998 }
0999 };
1000 template<
1001 typename ROW
1002 >
1003 struct _internal_ <ROW,library_sm>
1004 {
1005 typedef library_sm current_state_type;
1006 typedef library_sm next_state_type;
1007 typedef typename ROW::Evt transition_event;
1008 static HandledEnum execute(library_sm& , int , int , transition_event const& )
1009 {
1010 return HANDLED_TRUE;
1011 }
1012 };
1013
1014 template<
1015 typename T1
1016 , class Evt
1017 >
1018 struct frow
1019 {
1020 typedef T1 current_state_type;
1021 typedef T1 next_state_type;
1022 typedef Evt transition_event;
1023
1024 typedef int is_frow;
1025
1026
1027 static HandledEnum execute(library_sm& fsm, int region_index, int , transition_event const& evt)
1028 {
1029
1030 execute_return res =
1031 (::boost::fusion::at_key<current_state_type>(fsm.m_substate_list)).process_event_internal(evt);
1032 fsm.m_states[region_index]=get_state_id<stt,T1>::type::value;
1033 return res;
1034 }
1035
1036
1037 template <class NewEvent>
1038 struct replace_event
1039 {
1040 typedef frow<T1,NewEvent> type;
1041 };
1042 };
1043
1044 template <class Tag, class Transition,class StateType>
1045 struct create_backend_stt
1046 {
1047 };
1048 template <class Transition,class StateType>
1049 struct create_backend_stt<g_row_tag,Transition,StateType>
1050 {
1051 typedef g_row_<Transition> type;
1052 };
1053 template <class Transition,class StateType>
1054 struct create_backend_stt<a_row_tag,Transition,StateType>
1055 {
1056 typedef a_row_<Transition> type;
1057 };
1058 template <class Transition,class StateType>
1059 struct create_backend_stt<_row_tag,Transition,StateType>
1060 {
1061 typedef _row_<Transition> type;
1062 };
1063 template <class Transition,class StateType>
1064 struct create_backend_stt<row_tag,Transition,StateType>
1065 {
1066 typedef row_<Transition> type;
1067 };
1068
1069 template <class Transition,class StateType>
1070 struct create_backend_stt<g_irow_tag,Transition,StateType>
1071 {
1072 typedef g_irow_<Transition> type;
1073 };
1074 template <class Transition,class StateType>
1075 struct create_backend_stt<a_irow_tag,Transition,StateType>
1076 {
1077 typedef a_irow_<Transition> type;
1078 };
1079 template <class Transition,class StateType>
1080 struct create_backend_stt<irow_tag,Transition,StateType>
1081 {
1082 typedef irow_<Transition> type;
1083 };
1084 template <class Transition,class StateType>
1085 struct create_backend_stt<_irow_tag,Transition,StateType>
1086 {
1087 typedef _irow_<Transition> type;
1088 };
1089 template <class Transition,class StateType>
1090 struct create_backend_stt<sm_a_i_row_tag,Transition,StateType>
1091 {
1092 typedef a_internal_<Transition,StateType> type;
1093 };
1094 template <class Transition,class StateType>
1095 struct create_backend_stt<sm_g_i_row_tag,Transition,StateType>
1096 {
1097 typedef g_internal_<Transition,StateType> type;
1098 };
1099 template <class Transition,class StateType>
1100 struct create_backend_stt<sm_i_row_tag,Transition,StateType>
1101 {
1102 typedef internal_<Transition,StateType> type;
1103 };
1104 template <class Transition,class StateType>
1105 struct create_backend_stt<sm__i_row_tag,Transition,StateType>
1106 {
1107 typedef _internal_<Transition,StateType> type;
1108 };
1109 template <class Transition,class StateType=void>
1110 struct make_row_tag
1111 {
1112 typedef typename create_backend_stt<typename Transition::row_type_tag,Transition,StateType>::type type;
1113 };
1114
1115
1116 template <class BaseType, class stt_simulated = typename BaseType::transition_table>
1117 struct create_real_stt
1118 {
1119
1120 typedef typename ::boost::mpl::fold<
1121 stt_simulated,mpl::vector0<>,
1122 ::boost::mpl::push_back< ::boost::mpl::placeholders::_1,
1123 make_row_tag< ::boost::mpl::placeholders::_2 , BaseType > >
1124 >::type type;
1125 };
1126
1127 template <class Table,class Intermediate,class StateType>
1128 struct add_forwarding_row_helper
1129 {
1130 typedef typename generate_event_set<Table>::type all_events;
1131 typedef typename ::boost::mpl::fold<
1132 all_events, Intermediate,
1133 ::boost::mpl::push_back< ::boost::mpl::placeholders::_1,
1134 frow<StateType, ::boost::mpl::placeholders::_2> > >::type type;
1135 };
1136
1137 template <class StateType,class IsComposite>
1138 struct get_internal_transition_table
1139 {
1140
1141 typedef typename recursive_get_transition_table<StateType>::type original_table;
1142
1143
1144
1145
1146 typedef typename recursive_get_internal_transition_table<StateType, ::boost::mpl::true_>::type recursive_istt;
1147 typedef typename ::boost::mpl::fold<
1148 recursive_istt,::boost::mpl::vector0<>,
1149 ::boost::mpl::push_back< ::boost::mpl::placeholders::_1,
1150 make_row_tag< ::boost::mpl::placeholders::_2 , StateType> >
1151 >::type recursive_istt_with_tag;
1152
1153 typedef typename ::boost::mpl::insert_range< original_table, typename ::boost::mpl::end<original_table>::type,
1154 recursive_istt_with_tag>::type table_with_all_events;
1155
1156
1157 typedef typename ::boost::mpl::eval_if<
1158 typename CompilePolicy::add_forwarding_rows,
1159 add_forwarding_row_helper<table_with_all_events,::boost::mpl::vector0<>,StateType>,
1160 ::boost::mpl::identity< ::boost::mpl::vector0<> >
1161 >::type type;
1162 };
1163 template <class StateType>
1164 struct get_internal_transition_table<StateType, ::boost::mpl::false_ >
1165 {
1166 typedef typename create_real_stt<StateType, typename StateType::internal_transition_table >::type type;
1167 };
1168
1169 typedef typename create_real_stt<Derived>::type real_transition_table;
1170 typedef typename create_stt<library_sm>::type stt;
1171 typedef typename get_initial_states<typename Derived::initial_state>::type initial_states;
1172 typedef typename generate_state_set<stt>::type state_list;
1173 typedef typename HistoryPolicy::template apply<nr_regions::value>::type concrete_history;
1174
1175 typedef typename ::boost::fusion::result_of::as_set<state_list>::type substate_list;
1176 typedef typename ::boost::msm::back::generate_event_set<
1177 typename create_real_stt<library_sm, typename library_sm::internal_transition_table >::type
1178 >::type processable_events_internal_table;
1179
1180
1181 template <class Composite>
1182 struct extend_table
1183 {
1184
1185
1186 typedef typename Composite::stt Stt;
1187
1188
1189
1190
1191
1192 typedef typename ::boost::mpl::fold<
1193 typename Composite::internal_transition_table,::boost::mpl::vector0<>,
1194 ::boost::mpl::push_back< ::boost::mpl::placeholders::_1,
1195 make_row_tag< ::boost::mpl::placeholders::_2 , Composite> >
1196 >::type internal_stt;
1197
1198 typedef typename ::boost::mpl::insert_range<
1199 Stt,
1200 typename ::boost::mpl::end<Stt>::type,
1201 internal_stt
1202
1203 >::type stt_plus_internal;
1204
1205
1206
1207 typedef typename ::boost::mpl::fold<state_list,stt_plus_internal,
1208 ::boost::mpl::insert_range<
1209 ::boost::mpl::placeholders::_1,
1210 ::boost::mpl::end< ::boost::mpl::placeholders::_1>,
1211 get_internal_transition_table<
1212 ::boost::mpl::placeholders::_2,
1213 is_composite_state< ::boost::mpl::placeholders::_2> > >
1214 >::type type;
1215 };
1216
1217 typedef typename extend_table<library_sm>::type complete_table;
1218
1219 typedef typename get_regions_as_sequence<typename Derived::initial_state>::type seq_initial_states;
1220
1221
1222
1223 void start()
1224 {
1225
1226 ::boost::mpl::for_each< seq_initial_states, ::boost::msm::wrap<mpl::placeholders::_1> >
1227 (init_states(m_states));
1228
1229 (static_cast<Derived*>(this))->on_entry(fsm_initial_event(),*this);
1230 ::boost::mpl::for_each<initial_states, boost::msm::wrap<mpl::placeholders::_1> >
1231 (call_init<fsm_initial_event>(fsm_initial_event(),this));
1232
1233 handle_eventless_transitions_helper<library_sm> eventless_helper(this,true);
1234 eventless_helper.process_completion_event();
1235 }
1236
1237
1238 template <class Event>
1239 void start(Event const& incomingEvent)
1240 {
1241
1242 ::boost::mpl::for_each< seq_initial_states, ::boost::msm::wrap<mpl::placeholders::_1> >
1243 (init_states(m_states));
1244
1245 (static_cast<Derived*>(this))->on_entry(incomingEvent,*this);
1246 ::boost::mpl::for_each<initial_states, boost::msm::wrap<mpl::placeholders::_1> >
1247 (call_init<Event>(incomingEvent,this));
1248
1249 handle_eventless_transitions_helper<library_sm> eventless_helper(this,true);
1250 eventless_helper.process_completion_event();
1251 }
1252
1253
1254 void stop()
1255 {
1256 do_exit(fsm_final_event(),*this);
1257 }
1258
1259
1260 template <class Event>
1261 void stop(Event const& finalEvent)
1262 {
1263 do_exit(finalEvent,*this);
1264 }
1265
1266
1267 template<class Event>
1268 execute_return process_event(Event const& evt)
1269 {
1270 return process_event_internal(evt, EVENT_SOURCE_DIRECT);
1271 }
1272
1273 template <class EventType>
1274 void enqueue_event_helper(EventType const& evt, ::boost::mpl::false_ const &)
1275 {
1276 execute_return (library_sm::*pf) (EventType const&, EventSource) =
1277 &library_sm::process_event_internal;
1278
1279 m_events_queue.m_events_queue.push_back(
1280 ::boost::bind(
1281 pf, this, evt,
1282 static_cast<EventSource>(EVENT_SOURCE_MSG_QUEUE)));
1283 }
1284 template <class EventType>
1285 void enqueue_event_helper(EventType const& , ::boost::mpl::true_ const &)
1286 {
1287
1288 }
1289
1290 void execute_queued_events_helper(::boost::mpl::false_ const &)
1291 {
1292 while(!m_events_queue.m_events_queue.empty())
1293 {
1294 transition_fct to_call = m_events_queue.m_events_queue.front();
1295 m_events_queue.m_events_queue.pop_front();
1296 to_call();
1297 }
1298 }
1299 void execute_queued_events_helper(::boost::mpl::true_ const &)
1300 {
1301
1302 }
1303 void execute_single_queued_event_helper(::boost::mpl::false_ const &)
1304 {
1305 transition_fct to_call = m_events_queue.m_events_queue.front();
1306 m_events_queue.m_events_queue.pop_front();
1307 to_call();
1308 }
1309 void execute_single_queued_event_helper(::boost::mpl::true_ const &)
1310 {
1311
1312 }
1313
1314
1315
1316
1317 template <class EventType>
1318 void enqueue_event(EventType const& evt)
1319 {
1320 enqueue_event_helper<EventType>(evt, typename is_no_message_queue<library_sm>::type());
1321 }
1322
1323
1324 void execute_queued_events()
1325 {
1326 execute_queued_events_helper(typename is_no_message_queue<library_sm>::type());
1327 }
1328 void execute_single_queued_event()
1329 {
1330 execute_single_queued_event_helper(typename is_no_message_queue<library_sm>::type());
1331 }
1332 typename events_queue_t::size_type get_message_queue_size() const
1333 {
1334 return m_events_queue.m_events_queue.size();
1335 }
1336
1337 events_queue_t& get_message_queue()
1338 {
1339 return m_events_queue.m_events_queue;
1340 }
1341
1342 const events_queue_t& get_message_queue() const
1343 {
1344 return m_events_queue.m_events_queue;
1345 }
1346
1347 void clear_deferred_queue()
1348 {
1349 m_deferred_events_queue.clear();
1350 }
1351
1352 deferred_events_queue_t& get_deferred_queue()
1353 {
1354 return m_deferred_events_queue.m_deferred_events_queue;
1355 }
1356
1357 const deferred_events_queue_t& get_deferred_queue() const
1358 {
1359 return m_deferred_events_queue.m_deferred_events_queue;
1360 }
1361
1362
1363 const int* current_state() const
1364 {
1365 return this->m_states;
1366 }
1367
1368 template <class Archive>
1369 struct serialize_state
1370 {
1371 serialize_state(Archive& ar):ar_(ar){}
1372
1373 template<typename T>
1374 typename ::boost::enable_if<
1375 typename ::boost::mpl::or_<
1376 typename has_do_serialize<T>::type,
1377 typename is_composite_state<T>::type
1378 >::type
1379 ,void
1380 >::type
1381 operator()(T& t) const
1382 {
1383 ar_ & t;
1384 }
1385 template<typename T>
1386 typename ::boost::disable_if<
1387 typename ::boost::mpl::or_<
1388 typename has_do_serialize<T>::type,
1389 typename is_composite_state<T>::type
1390 >::type
1391 ,void
1392 >::type
1393 operator()(T&) const
1394 {
1395
1396 }
1397 Archive& ar_;
1398 };
1399
1400 template<class Archive>
1401 void serialize(Archive & ar, const unsigned int)
1402 {
1403
1404 (serialize_state<Archive>(ar))(boost::serialization::base_object<Derived>(*this));
1405
1406 ar & m_states;
1407
1408 ar & m_history;
1409 ar & m_event_processing;
1410 ar & m_is_included;
1411
1412 ::boost::fusion::for_each(m_substate_list, serialize_state<Archive>(ar));
1413 }
1414
1415
1416 struct get_state_id_helper
1417 {
1418 get_state_id_helper(int id,const BaseState** res,const library_sm* self_):
1419 result_state(res),searched_id(id),self(self_) {}
1420
1421 template <class StateType>
1422 void operator()(boost::msm::wrap<StateType> const&)
1423 {
1424
1425 BOOST_STATIC_CONSTANT(int, id = (get_state_id<stt,StateType>::value));
1426 if (!*result_state && (id == searched_id))
1427 {
1428 *result_state = &::boost::fusion::at_key<StateType>(self->m_substate_list);
1429 }
1430 }
1431 const BaseState** result_state;
1432 int searched_id;
1433 const library_sm* self;
1434 };
1435
1436
1437
1438 BaseState* get_state_by_id(int id)
1439 {
1440 const BaseState* result_state=0;
1441 ::boost::mpl::for_each<state_list,
1442 ::boost::msm::wrap< ::boost::mpl::placeholders::_1> > (get_state_id_helper(id,&result_state,this));
1443 return const_cast<BaseState*>(result_state);
1444 }
1445 const BaseState* get_state_by_id(int id) const
1446 {
1447 const BaseState* result_state=0;
1448 ::boost::mpl::for_each<state_list,
1449 ::boost::msm::wrap< ::boost::mpl::placeholders::_1> > (get_state_id_helper(id,&result_state,this));
1450 return result_state;
1451 }
1452
1453 bool is_contained() const
1454 {
1455 return m_is_included;
1456 }
1457
1458 concrete_history& get_history()
1459 {
1460 return m_history;
1461 }
1462 concrete_history const& get_history() const
1463 {
1464 return m_history;
1465 }
1466
1467
1468 template <class State>
1469 typename ::boost::enable_if<typename ::boost::is_pointer<State>::type,State >::type
1470 get_state(::boost::msm::back::dummy<0> = 0) const
1471 {
1472 return const_cast<State >
1473 (&
1474 (::boost::fusion::at_key<
1475 typename ::boost::remove_const<typename ::boost::remove_pointer<State>::type>::type>(m_substate_list)));
1476 }
1477
1478 template <class State>
1479 typename ::boost::enable_if<typename ::boost::is_reference<State>::type,State >::type
1480 get_state(::boost::msm::back::dummy<1> = 0) const
1481 {
1482 return const_cast<State >
1483 ( ::boost::fusion::at_key<
1484 typename ::boost::remove_const<typename ::boost::remove_reference<State>::type>::type>(m_substate_list) );
1485 }
1486
1487
1488 template <class State>
1489 typename ::boost::enable_if<typename ::boost::is_pointer<State>::type,State >::type
1490 get_state(::boost::msm::back::dummy<0> = 0)
1491 {
1492 return &(static_cast<typename boost::add_reference<typename ::boost::remove_pointer<State>::type>::type >
1493 (::boost::fusion::at_key<typename ::boost::remove_pointer<State>::type>(m_substate_list)));
1494 }
1495
1496 template <class State>
1497 typename ::boost::enable_if<typename ::boost::is_reference<State>::type,State >::type
1498 get_state(::boost::msm::back::dummy<1> = 0)
1499 {
1500 return ::boost::fusion::at_key<typename ::boost::remove_reference<State>::type>(m_substate_list);
1501 }
1502
1503 template <class Flag,class BinaryOp>
1504 bool is_flag_active() const
1505 {
1506 flag_handler* flags_entries = get_entries_for_flag<Flag>();
1507 bool res = (*flags_entries[ m_states[0] ])(*this);
1508 for (int i = 1; i < nr_regions::value ; ++i)
1509 {
1510 res = typename BinaryOp::type() (res,(*flags_entries[ m_states[i] ])(*this));
1511 }
1512 return res;
1513 }
1514
1515 template <class Flag>
1516 bool is_flag_active() const
1517 {
1518 return FlagHelper<Flag,(nr_regions::value>1)>::helper(*this,get_entries_for_flag<Flag>());
1519 }
1520
1521
1522 void visit_current_states()
1523 {
1524 for (int i=0; i<nr_regions::value;++i)
1525 {
1526 m_visitors.execute(m_states[i]);
1527 }
1528 }
1529 #define MSM_VISIT_STATE_SUB(z, n, unused) ARG ## n vis ## n
1530 #define MSM_VISIT_STATE_EXECUTE(z, n, unused) \
1531 template <BOOST_PP_ENUM_PARAMS(n, class ARG)> \
1532 void visit_current_states(BOOST_PP_ENUM(n, MSM_VISIT_STATE_SUB, ~ ) ) \
1533 { \
1534 for (int i=0; i<nr_regions::value;++i) \
1535 { \
1536 m_visitors.execute(m_states[i],BOOST_PP_ENUM_PARAMS(n,vis)); \
1537 } \
1538 }
1539 BOOST_PP_REPEAT_FROM_TO(1,BOOST_PP_ADD(BOOST_MSM_VISITOR_ARG_SIZE,1), MSM_VISIT_STATE_EXECUTE, ~)
1540 #undef MSM_VISIT_STATE_EXECUTE
1541 #undef MSM_VISIT_STATE_SUB
1542
1543
1544 template <class Event>
1545 typename::boost::disable_if< typename ::boost::msm::is_kleene_event<Event>::type, void>::type
1546 defer_event(Event const& e)
1547 {
1548
1549
1550 BOOST_MPL_ASSERT(( has_fsm_deferred_events<library_sm> ));
1551 execute_return (library_sm::*pf) (Event const&, EventSource) =
1552 &library_sm::process_event_internal;
1553
1554
1555
1556
1557 m_deferred_events_queue.m_deferred_events_queue.push_back(
1558 std::make_pair(
1559 ::boost::bind(
1560 pf, this, e, static_cast<EventSource>(EVENT_SOURCE_DIRECT|EVENT_SOURCE_DEFERRED)),
1561 static_cast<char>(m_deferred_events_queue.m_cur_seq+1)));
1562 }
1563 protected:
1564 template <class KleeneEvent, class Fsm>
1565 struct defer_event_kleene_helper
1566 {
1567 defer_event_kleene_helper(KleeneEvent const& e, Fsm* fsm, bool& found)
1568 : m_event(e), m_fsm(fsm), m_found(found) {}
1569
1570
1571 template <class Event>
1572 void operator()(Event const& ev)
1573 {
1574 if (m_event.type() == boost::typeindex::type_id<decltype(ev)>().type_info())
1575 {
1576 m_found = true;
1577
1578
1579 BOOST_MPL_ASSERT((has_fsm_deferred_events<library_sm>));
1580 ::boost::msm::back::execute_return(library_sm:: * pf) (Event const&, ::boost::msm::back::EventSource) =
1581 &library_sm::process_event_internal;
1582
1583
1584
1585
1586 m_fsm->m_deferred_events_queue.m_deferred_events_queue.push_back(
1587 std::make_pair(
1588 ::boost::bind(
1589 pf, m_fsm, boost::any_cast<Event>(m_event), static_cast<::boost::msm::back::EventSource>(::boost::msm::back::EVENT_SOURCE_DIRECT | ::boost::msm::back::EVENT_SOURCE_DEFERRED)),
1590 static_cast<char>(m_fsm->m_deferred_events_queue.m_cur_seq + 1)));
1591 }
1592 }
1593 KleeneEvent const& m_event;
1594 Fsm* m_fsm;
1595 bool& m_found;
1596 };
1597
1598 public:
1599 template <class Event>
1600 typename::boost::enable_if< typename ::boost::msm::is_kleene_event<Event>::type, void>::type
1601 defer_event(Event const& e)
1602 {
1603 typedef typename generate_event_set<stt>::type event_list;
1604 bool found = false;
1605 boost::fusion::for_each(
1606 event_list(),
1607 defer_event_kleene_helper<Event,library_sm>(e,this,found));
1608 if (!found)
1609 {
1610 for (int i = 0; i < nr_regions::value; ++i)
1611 {
1612 this->no_transition(e, *this, this->m_states[i]);
1613 }
1614 }
1615 }
1616
1617
1618 protected:
1619
1620
1621 struct init_states
1622 {
1623 init_states(int* const init):m_initial_states(init),m_index(-1){}
1624
1625
1626 template <class State>
1627 void operator()(::boost::msm::wrap<State> const&)
1628 {
1629 m_initial_states[++m_index]=get_state_id<stt,State>::type::value;
1630 }
1631 int* const m_initial_states;
1632 int m_index;
1633 };
1634 public:
1635 struct update_state
1636 {
1637 update_state(substate_list& to_overwrite_):to_overwrite(&to_overwrite_){}
1638 template<typename StateType>
1639 void operator()(StateType const& astate) const
1640 {
1641 ::boost::fusion::at_key<StateType>(*to_overwrite)=astate;
1642 }
1643 substate_list* to_overwrite;
1644 };
1645 template <class Expr>
1646 void set_states(Expr const& expr)
1647 {
1648 ::boost::fusion::for_each(
1649 ::boost::fusion::as_vector(FoldToList()(expr, boost::fusion::nil_())),update_state(this->m_substate_list));
1650 }
1651
1652
1653 state_machine()
1654 :Derived()
1655 ,m_events_queue()
1656 ,m_deferred_events_queue()
1657 ,m_history()
1658 ,m_event_processing(false)
1659 ,m_is_included(false)
1660 ,m_visitors()
1661 ,m_substate_list()
1662 {
1663
1664 ::boost::mpl::for_each< seq_initial_states, ::boost::msm::wrap<mpl::placeholders::_1> >
1665 (init_states(m_states));
1666 m_history.set_initial_states(m_states);
1667
1668 fill_states(this);
1669 }
1670
1671
1672 #if defined (BOOST_NO_CXX11_RVALUE_REFERENCES) \
1673 || defined (BOOST_NO_CXX11_VARIADIC_TEMPLATES) \
1674 || defined (BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS)
1675 template <class Expr>
1676 state_machine
1677 (Expr const& expr, typename ::boost::enable_if<typename ::boost::proto::is_expr<Expr>::type >::type* = 0)
1678 :Derived()
1679 , m_events_queue()
1680 , m_deferred_events_queue()
1681 , m_history()
1682 , m_event_processing(false)
1683 , m_is_included(false)
1684 , m_visitors()
1685 , m_substate_list()
1686 {
1687 BOOST_MPL_ASSERT_MSG(
1688 (::boost::proto::matches<Expr, FoldToList>::value),
1689 THE_STATES_EXPRESSION_PASSED_DOES_NOT_MATCH_GRAMMAR,
1690 (FoldToList));
1691
1692
1693 ::boost::mpl::for_each< seq_initial_states, ::boost::msm::wrap<mpl::placeholders::_1> >
1694 (init_states(m_states));
1695 m_history.set_initial_states(m_states);
1696
1697 set_states(expr);
1698 fill_states(this);
1699 }
1700 #define MSM_CONSTRUCTOR_HELPER_EXECUTE_SUB(z, n, unused) ARG ## n t ## n
1701 #define MSM_CONSTRUCTOR_HELPER_EXECUTE(z, n, unused) \
1702 template <BOOST_PP_ENUM_PARAMS(n, class ARG)> \
1703 state_machine<A0,A1,A2,A3,A4 \
1704 >(BOOST_PP_ENUM(n, MSM_CONSTRUCTOR_HELPER_EXECUTE_SUB, ~ ), \
1705 typename ::boost::disable_if<typename ::boost::proto::is_expr<ARG0>::type >::type* =0 ) \
1706 :Derived(BOOST_PP_ENUM_PARAMS(n,t)) \
1707 ,m_events_queue() \
1708 ,m_deferred_events_queue() \
1709 ,m_history() \
1710 ,m_event_processing(false) \
1711 ,m_is_included(false) \
1712 ,m_visitors() \
1713 ,m_substate_list() \
1714 { \
1715 ::boost::mpl::for_each< seq_initial_states, ::boost::msm::wrap<mpl::placeholders::_1> > \
1716 (init_states(m_states)); \
1717 m_history.set_initial_states(m_states); \
1718 fill_states(this); \
1719 } \
1720 template <class Expr,BOOST_PP_ENUM_PARAMS(n, class ARG)> \
1721 state_machine<A0,A1,A2,A3,A4 \
1722 >(Expr const& expr,BOOST_PP_ENUM(n, MSM_CONSTRUCTOR_HELPER_EXECUTE_SUB, ~ ), \
1723 typename ::boost::enable_if<typename ::boost::proto::is_expr<Expr>::type >::type* =0 ) \
1724 :Derived(BOOST_PP_ENUM_PARAMS(n,t)) \
1725 ,m_events_queue() \
1726 ,m_deferred_events_queue() \
1727 ,m_history() \
1728 ,m_event_processing(false) \
1729 ,m_is_included(false) \
1730 ,m_visitors() \
1731 ,m_substate_list() \
1732 { \
1733 BOOST_MPL_ASSERT_MSG( \
1734 ( ::boost::proto::matches<Expr, FoldToList>::value), \
1735 THE_STATES_EXPRESSION_PASSED_DOES_NOT_MATCH_GRAMMAR, \
1736 (FoldToList)); \
1737 ::boost::mpl::for_each< seq_initial_states, ::boost::msm::wrap<mpl::placeholders::_1> > \
1738 (init_states(m_states)); \
1739 m_history.set_initial_states(m_states); \
1740 set_states(expr); \
1741 fill_states(this); \
1742 }
1743
1744 BOOST_PP_REPEAT_FROM_TO(1,BOOST_PP_ADD(BOOST_MSM_CONSTRUCTOR_ARG_SIZE,1), MSM_CONSTRUCTOR_HELPER_EXECUTE, ~)
1745 #undef MSM_CONSTRUCTOR_HELPER_EXECUTE
1746 #undef MSM_CONSTRUCTOR_HELPER_EXECUTE_SUB
1747
1748 #else
1749 template <class ARG0,class... ARG,class=typename ::boost::disable_if<typename ::boost::proto::is_expr<ARG0>::type >::type>
1750 state_machine(ARG0&& t0,ARG&&... t)
1751 :Derived(std::forward<ARG0>(t0), std::forward<ARG>(t)...)
1752 ,m_events_queue()
1753 ,m_deferred_events_queue()
1754 ,m_history()
1755 ,m_event_processing(false)
1756 ,m_is_included(false)
1757 ,m_visitors()
1758 ,m_substate_list()
1759 {
1760 ::boost::mpl::for_each< seq_initial_states, ::boost::msm::wrap<mpl::placeholders::_1> >
1761 (init_states(m_states));
1762 m_history.set_initial_states(m_states);
1763 fill_states(this);
1764 }
1765 template <class Expr,class... ARG,class=typename ::boost::enable_if<typename ::boost::proto::is_expr<Expr>::type >::type>
1766 state_machine(Expr const& expr,ARG&&... t)
1767 :Derived(std::forward<ARG>(t)...)
1768 ,m_events_queue()
1769 ,m_deferred_events_queue()
1770 ,m_history()
1771 ,m_event_processing(false)
1772 ,m_is_included(false)
1773 ,m_visitors()
1774 ,m_substate_list()
1775 {
1776 BOOST_MPL_ASSERT_MSG(
1777 ( ::boost::proto::matches<Expr, FoldToList>::value),
1778 THE_STATES_EXPRESSION_PASSED_DOES_NOT_MATCH_GRAMMAR,
1779 (FoldToList));
1780 ::boost::mpl::for_each< seq_initial_states, ::boost::msm::wrap<mpl::placeholders::_1> >
1781 (init_states(m_states));
1782 m_history.set_initial_states(m_states);
1783 set_states(expr);
1784 fill_states(this);
1785 }
1786 #endif
1787
1788
1789
1790 library_sm& operator= (library_sm const& rhs)
1791 {
1792 if (this != &rhs)
1793 {
1794 Derived::operator=(rhs);
1795 do_copy(rhs);
1796 }
1797 return *this;
1798 }
1799 state_machine(library_sm const& rhs)
1800 : Derived(rhs)
1801 {
1802 if (this != &rhs)
1803 {
1804
1805 fill_states(this);
1806 do_copy(rhs);
1807 }
1808 }
1809
1810
1811
1812 template <class Event>
1813 bool is_event_handling_blocked_helper( ::boost::mpl::true_ const &)
1814 {
1815
1816 if (is_flag_active< ::boost::msm::TerminateFlag>())
1817 return true;
1818
1819
1820 if ( is_flag_active< ::boost::msm::InterruptedFlag>() &&
1821 !is_flag_active< ::boost::msm::EndInterruptFlag<Event> >())
1822 return true;
1823 return false;
1824 }
1825
1826 template <class Event>
1827 bool is_event_handling_blocked_helper( ::boost::mpl::false_ const &)
1828 {
1829
1830 return false;
1831 }
1832 void do_handle_prio_msg_queue_deferred_queue(EventSource source, HandledEnum handled, ::boost::mpl::true_ const &)
1833 {
1834
1835 if (!(EVENT_SOURCE_MSG_QUEUE & source))
1836 {
1837 do_post_msg_queue_helper(
1838 ::boost::mpl::bool_<
1839 is_no_message_queue<library_sm>::type::value>());
1840 if (!(EVENT_SOURCE_DEFERRED & source))
1841 {
1842 handle_defer_helper<library_sm> defer_helper(m_deferred_events_queue);
1843 defer_helper.do_handle_deferred(HANDLED_TRUE & handled);
1844 }
1845 }
1846 }
1847 void do_handle_prio_msg_queue_deferred_queue(EventSource source, HandledEnum handled, ::boost::mpl::false_ const &)
1848 {
1849
1850 if (!(EVENT_SOURCE_DEFERRED & source))
1851 {
1852 handle_defer_helper<library_sm> defer_helper(m_deferred_events_queue);
1853 defer_helper.do_handle_deferred(HANDLED_TRUE & handled);
1854
1855
1856
1857 if (!(EVENT_SOURCE_MSG_QUEUE & source))
1858 {
1859 do_post_msg_queue_helper(
1860 ::boost::mpl::bool_<
1861 is_no_message_queue<library_sm>::type::value>());
1862 }
1863 }
1864 }
1865
1866 template <class StateType,class EventType>
1867 bool do_pre_msg_queue_helper(EventType const&, ::boost::mpl::true_ const &)
1868 {
1869
1870 return true;
1871 }
1872 template <class StateType,class EventType>
1873 bool do_pre_msg_queue_helper(EventType const& evt, ::boost::mpl::false_ const &)
1874 {
1875 execute_return (library_sm::*pf) (EventType const&, EventSource) =
1876 &library_sm::process_event_internal;
1877
1878
1879 if (m_event_processing)
1880 {
1881
1882 m_events_queue.m_events_queue.push_back(
1883 ::boost::bind(
1884 pf, this, evt,
1885 static_cast<EventSource>(EVENT_SOURCE_DIRECT | EVENT_SOURCE_MSG_QUEUE)));
1886
1887 return false;
1888 }
1889
1890
1891 m_event_processing = true;
1892 return true;
1893 }
1894 void do_post_msg_queue_helper( ::boost::mpl::true_ const &)
1895 {
1896
1897 }
1898 void do_post_msg_queue_helper( ::boost::mpl::false_ const &)
1899 {
1900 process_message_queue(this);
1901 }
1902 void do_allow_event_processing_after_transition( ::boost::mpl::true_ const &)
1903 {
1904
1905 }
1906 void do_allow_event_processing_after_transition( ::boost::mpl::false_ const &)
1907 {
1908 m_event_processing = false;
1909 }
1910
1911 template <class StateType,class EventType>
1912 HandledEnum do_process_helper(EventType const& evt, ::boost::mpl::true_ const &, bool is_direct_call)
1913 {
1914 return this->do_process_event(evt,is_direct_call);
1915 }
1916 template <class StateType,class EventType>
1917 HandledEnum do_process_helper(EventType const& evt, ::boost::mpl::false_ const &, bool is_direct_call)
1918 {
1919
1920
1921
1922 std::exception e;
1923 BOOST_TRY
1924 {
1925 return this->do_process_event(evt,is_direct_call);
1926 }
1927 BOOST_CATCH (std::exception& e)
1928 {
1929
1930 this->exception_caught(evt,*this,e);
1931 return ::boost::msm::back::HANDLED_FALSE;
1932 }
1933 BOOST_CATCH_END
1934 return HANDLED_TRUE;
1935 }
1936
1937
1938 template <class StateType, class Enable = int>
1939 struct handle_defer_helper
1940 {
1941 handle_defer_helper(deferred_msg_queue_helper<library_sm>& ){}
1942 void do_handle_deferred(bool)
1943 {
1944 }
1945 };
1946
1947 template <class StateType>
1948 struct handle_defer_helper
1949 <StateType, typename enable_if< typename ::boost::msm::back::has_fsm_deferred_events<StateType>::type,int >::type>
1950 {
1951 struct sort_greater
1952 {
1953 bool operator()(
1954 typename deferred_events_queue_t::value_type const& d1,
1955 typename deferred_events_queue_t::value_type const& d2)
1956 {
1957 return d1.second > d2.second;
1958 }
1959 };
1960 struct set_sequence
1961 {
1962 set_sequence(char s) :seq_(s) {}
1963 void operator()(typename deferred_events_queue_t::value_type& d)
1964 {
1965 d.second = seq_;
1966 }
1967 char seq_;
1968 };
1969 handle_defer_helper(deferred_msg_queue_helper<library_sm>& a_queue):
1970 m_events_queue(a_queue) {}
1971 void do_handle_deferred(bool new_seq=false)
1972 {
1973
1974
1975
1976
1977 if (new_seq)
1978 {
1979 ++m_events_queue.m_cur_seq;
1980 }
1981
1982 char& cur_seq = m_events_queue.m_cur_seq;
1983
1984
1985
1986
1987 bool not_only_deferred = false;
1988 while (!m_events_queue.m_deferred_events_queue.empty())
1989 {
1990 typename deferred_events_queue_t::value_type& pair =
1991 m_events_queue.m_deferred_events_queue.front();
1992
1993 if (cur_seq != pair.second)
1994 {
1995 break;
1996 }
1997
1998 deferred_fct next = pair.first;
1999 m_events_queue.m_deferred_events_queue.pop_front();
2000 boost::msm::back::execute_return res = next();
2001 if (res != ::boost::msm::back::HANDLED_FALSE && res != ::boost::msm::back::HANDLED_DEFERRED)
2002 {
2003 not_only_deferred = true;
2004 }
2005 if (not_only_deferred)
2006 {
2007
2008 break;
2009 }
2010 }
2011 if (not_only_deferred)
2012 {
2013
2014
2015
2016 std::stable_sort(
2017 m_events_queue.m_deferred_events_queue.begin(),
2018 m_events_queue.m_deferred_events_queue.end(),
2019 sort_greater()
2020 );
2021
2022 std::for_each(
2023 m_events_queue.m_deferred_events_queue.begin(),
2024 m_events_queue.m_deferred_events_queue.end(),
2025 set_sequence(m_events_queue.m_cur_seq + 1)
2026 );
2027
2028 do_handle_deferred(true);
2029 }
2030 }
2031
2032 private:
2033 deferred_msg_queue_helper<library_sm>& m_events_queue;
2034 };
2035
2036
2037
2038 template <class StateType, class Enable = void>
2039 struct handle_eventless_transitions_helper
2040 {
2041 handle_eventless_transitions_helper(library_sm* , bool ){}
2042 void process_completion_event(EventSource = EVENT_SOURCE_DEFAULT){}
2043 };
2044
2045 template <class StateType>
2046 struct handle_eventless_transitions_helper
2047 <StateType, typename enable_if< typename ::boost::msm::back::has_fsm_eventless_transition<StateType>::type >::type>
2048 {
2049 handle_eventless_transitions_helper(library_sm* self_, bool handled_):self(self_),handled(handled_){}
2050 void process_completion_event(EventSource source = EVENT_SOURCE_DEFAULT)
2051 {
2052 typedef typename ::boost::mpl::deref<
2053 typename ::boost::mpl::begin<
2054 typename find_completion_events<StateType>::type
2055 >::type
2056 >::type first_completion_event;
2057 if (handled)
2058 {
2059 self->process_event_internal(
2060 first_completion_event(),
2061 source | EVENT_SOURCE_DIRECT);
2062 }
2063 }
2064
2065 private:
2066 library_sm* self;
2067 bool handled;
2068 };
2069
2070
2071 template<class Event>
2072 struct process_fsm_internal_table
2073 {
2074 typedef typename ::boost::mpl::has_key<processable_events_internal_table,Event>::type is_event_processable;
2075
2076
2077 static void process(Event const& evt,library_sm* self_,HandledEnum& result)
2078 {
2079 do_process(evt,self_,result,is_event_processable());
2080 }
2081 private:
2082
2083 static void do_process(Event const& evt,library_sm* self_,HandledEnum& result, ::boost::mpl::true_)
2084 {
2085 if (result != HANDLED_TRUE)
2086 {
2087 typedef dispatch_table<library_sm,complete_table,Event,CompilePolicy> table;
2088 HandledEnum res_internal = table::instance().entries[0](*self_, 0, self_->m_states[0], evt);
2089 result = (HandledEnum)((int)result | (int)res_internal);
2090 }
2091 }
2092
2093 static void do_process(Event const& ,library_sm* ,HandledEnum& , ::boost::mpl::false_)
2094 {
2095
2096 }
2097 };
2098
2099 template <class StateType,class Enable=void>
2100 struct region_processing_helper
2101 {
2102 public:
2103 region_processing_helper(library_sm* self_,HandledEnum& result_)
2104 :self(self_),result(result_){}
2105 template<class Event>
2106 void process(Event const& evt)
2107 {
2108
2109 typedef dispatch_table<library_sm,complete_table,Event,CompilePolicy> table;
2110
2111 HandledEnum res =
2112 table::instance().entries[self->m_states[0]+1](
2113 *self, 0, self->m_states[0], evt);
2114 result = (HandledEnum)((int)result | (int)res);
2115
2116 process_fsm_internal_table<Event>::process(evt,self,result);
2117 }
2118 library_sm* self;
2119 HandledEnum& result;
2120 };
2121
2122 template <class StateType>
2123 struct region_processing_helper<StateType,typename ::boost::enable_if<
2124 ::boost::mpl::is_sequence<typename StateType::initial_state> >::type>
2125 {
2126 private:
2127
2128 template <class region_id,int Dummy=0>
2129 struct In
2130 {
2131 template<class Event>
2132 static void process(Event const& evt,library_sm* self_,HandledEnum& result_)
2133 {
2134
2135 typedef dispatch_table<library_sm,complete_table,Event,CompilePolicy> table;
2136
2137 HandledEnum res =
2138 table::instance().entries[self_->m_states[region_id::value]+1](
2139 *self_, region_id::value , self_->m_states[region_id::value], evt);
2140 result_ = (HandledEnum)((int)result_ | (int)res);
2141 In< ::boost::mpl::int_<region_id::value+1> >::process(evt,self_,result_);
2142 }
2143 };
2144 template <int Dummy>
2145 struct In< ::boost::mpl::int_<nr_regions::value>,Dummy>
2146 {
2147
2148 template<class Event>
2149 static void process(Event const& evt,library_sm* self_,HandledEnum& result_)
2150 {
2151
2152 process_fsm_internal_table<Event>::process(evt,self_,result_);
2153 }
2154 };
2155 public:
2156 region_processing_helper(library_sm* self_,HandledEnum& result_)
2157 :self(self_),result(result_){}
2158 template<class Event>
2159 void process(Event const& evt)
2160 {
2161 In< ::boost::mpl::int_<0> >::process(evt,self,result);
2162 }
2163
2164 library_sm* self;
2165 HandledEnum& result;
2166 };
2167
2168
2169
2170 template<class Event>
2171 execute_return process_event_internal(Event const& evt,
2172 EventSource source = EVENT_SOURCE_DEFAULT)
2173 {
2174
2175 if (is_event_handling_blocked_helper<Event>
2176 ( ::boost::mpl::bool_<has_fsm_blocking_states<library_sm>::type::value>() ) )
2177 {
2178 return HANDLED_TRUE;
2179 }
2180
2181
2182 if (!do_pre_msg_queue_helper<Event>
2183 (evt,::boost::mpl::bool_<is_no_message_queue<library_sm>::type::value>()))
2184 {
2185
2186 return HANDLED_TRUE;
2187 }
2188 else
2189 {
2190
2191 HandledEnum handled = this->do_process_helper<Event>(
2192 evt,
2193 ::boost::mpl::bool_<is_no_exception_thrown<library_sm>::type::value>(),
2194 (EVENT_SOURCE_DIRECT & source));
2195
2196
2197
2198 do_allow_event_processing_after_transition(
2199 ::boost::mpl::bool_<is_no_message_queue<library_sm>::type::value>());
2200
2201
2202
2203 handle_eventless_transitions_helper<library_sm>
2204 eventless_helper(this,(HANDLED_TRUE & handled));
2205 eventless_helper.process_completion_event(source);
2206
2207
2208
2209 do_handle_prio_msg_queue_deferred_queue(
2210 source,handled,
2211 ::boost::mpl::bool_<has_event_queue_before_deferred_queue<library_sm>::type::value>());
2212 return handled;
2213 }
2214 }
2215
2216
2217 template<class Event>
2218 HandledEnum do_process_event(Event const& evt, bool is_direct_call)
2219 {
2220 HandledEnum handled = HANDLED_FALSE;
2221
2222
2223 region_processing_helper<Derived> helper(this,handled);
2224 helper.process(evt);
2225
2226
2227
2228
2229
2230
2231
2232 if ( (!is_contained() || is_direct_call) && !handled && !is_completion_event<Event>::type::value)
2233 {
2234 for (int i=0; i<nr_regions::value;++i)
2235 {
2236 this->no_transition(evt,*this,this->m_states[i]);
2237 }
2238 }
2239 return handled;
2240 }
2241
2242
2243 template <class Event>
2244 bool no_guard(Event const&){return true;}
2245 template <class Event>
2246 void no_action(Event const&){}
2247
2248 #ifndef BOOST_NO_RTTI
2249 HandledEnum process_any_event( ::boost::any const& evt);
2250 #endif
2251
2252 private:
2253
2254 void composite_accept()
2255 {
2256 this->accept();
2257 this->visit_current_states();
2258 }
2259
2260 #define MSM_COMPOSITE_ACCEPT_SUB(z, n, unused) ARG ## n vis ## n
2261 #define MSM_COMPOSITE_ACCEPT_SUB2(z, n, unused) boost::ref( vis ## n )
2262 #define MSM_COMPOSITE_ACCEPT_EXECUTE(z, n, unused) \
2263 template <BOOST_PP_ENUM_PARAMS(n, class ARG)> \
2264 void composite_accept(BOOST_PP_ENUM(n, MSM_COMPOSITE_ACCEPT_SUB, ~ ) ) \
2265 { \
2266 this->accept(BOOST_PP_ENUM_PARAMS(n,vis)); \
2267 this->visit_current_states(BOOST_PP_ENUM(n,MSM_COMPOSITE_ACCEPT_SUB2, ~)); \
2268 }
2269 BOOST_PP_REPEAT_FROM_TO(1,BOOST_PP_ADD(BOOST_MSM_VISITOR_ARG_SIZE,1), MSM_COMPOSITE_ACCEPT_EXECUTE, ~)
2270 #undef MSM_COMPOSITE_ACCEPT_EXECUTE
2271 #undef MSM_COMPOSITE_ACCEPT_SUB
2272 #undef MSM_COMPOSITE_ACCEPT_SUB2
2273
2274
2275 template <class Event>
2276 struct call_init
2277 {
2278 call_init(Event const& an_event,library_sm* self_):
2279 evt(an_event),self(self_){}
2280 template <class State>
2281 void operator()(boost::msm::wrap<State> const&)
2282 {
2283 execute_entry(::boost::fusion::at_key<State>(self->m_substate_list),evt,*self);
2284 }
2285 private:
2286 Event const& evt;
2287 library_sm* self;
2288 };
2289
2290 template <class Flag,bool orthogonalStates>
2291 struct FlagHelper
2292 {
2293 static bool helper(library_sm const& sm,flag_handler* )
2294 {
2295
2296 return sm.is_flag_active<Flag,Flag_OR>();
2297 }
2298 };
2299 template <class Flag>
2300 struct FlagHelper<Flag,false>
2301 {
2302 static bool helper(library_sm const& sm,flag_handler* flags_entries)
2303 {
2304
2305 return flags_entries[sm.current_state()[0]](sm);
2306 }
2307 };
2308
2309
2310 template <class StateType,class Flag>
2311 struct FlagHandler
2312 {
2313 static bool flag_true(library_sm const& )
2314 {
2315 return true;
2316 }
2317 static bool flag_false(library_sm const& )
2318 {
2319 return false;
2320 }
2321 static bool forward(library_sm const& fsm)
2322 {
2323 return ::boost::fusion::at_key<StateType>(fsm.m_substate_list).template is_flag_active<Flag>();
2324 }
2325 };
2326 template <class Flag>
2327 struct init_flags
2328 {
2329 private:
2330
2331 template <class T>
2332 void helper (flag_handler* an_entry,int offset, ::boost::mpl::true_ const & )
2333 {
2334
2335 an_entry[offset] = &FlagHandler<T,Flag>::forward;
2336 }
2337 template <class T>
2338 void helper (flag_handler* an_entry,int offset, ::boost::mpl::false_ const & )
2339 {
2340
2341 an_entry[offset] = &FlagHandler<T,Flag>::flag_false;
2342 }
2343
2344 flag_handler* entries;
2345
2346 public:
2347 init_flags(flag_handler* entries_)
2348 : entries(entries_)
2349 {}
2350
2351
2352 template <class StateType>
2353 void operator()( ::boost::msm::wrap<StateType> const& )
2354 {
2355 typedef typename get_flag_list<StateType>::type flags;
2356 typedef typename ::boost::mpl::contains<flags,Flag >::type found;
2357
2358 BOOST_STATIC_CONSTANT(int, state_id = (get_state_id<stt,StateType>::type::value));
2359 if (found::type::value)
2360 {
2361
2362 entries[state_id] = &FlagHandler<StateType,Flag>::flag_true;
2363 }
2364 else
2365 {
2366
2367 typedef typename ::boost::mpl::and_<
2368 typename is_composite_state<StateType>::type,
2369 typename ::boost::mpl::not_<
2370 typename has_non_forwarding_flag<Flag>::type>::type >::type composite_no_forward;
2371
2372 helper<StateType>(entries,state_id,::boost::mpl::bool_<composite_no_forward::type::value>());
2373 }
2374 }
2375 };
2376
2377 template <class Flag>
2378 flag_handler* get_entries_for_flag() const
2379 {
2380 BOOST_STATIC_CONSTANT(int, max_state = (mpl::size<state_list>::value));
2381
2382 static flag_handler flags_entries[max_state];
2383
2384 static flag_handler* flags_entries_ptr =
2385 (::boost::mpl::for_each<state_list, boost::msm::wrap< ::boost::mpl::placeholders::_1> >
2386 (init_flags<Flag>(flags_entries)),
2387 flags_entries);
2388 return flags_entries_ptr;
2389 }
2390
2391
2392 template <class State, class Enable=void>
2393 struct create_state_helper
2394 {
2395 static void set_sm(library_sm* )
2396 {
2397
2398 }
2399 };
2400
2401 template <class State>
2402 struct create_state_helper<State,typename boost::enable_if<typename State::needs_sm >::type>
2403 {
2404 static void set_sm(library_sm* sm)
2405 {
2406
2407 ::boost::fusion::at_key<State>(sm->m_substate_list).set_sm_ptr(sm);
2408 }
2409 };
2410
2411 template <class StateType,int ARGS>
2412 struct visitor_args;
2413
2414 #define MSM_VISITOR_ARGS_SUB(z, n, unused) BOOST_PP_CAT(::boost::placeholders::_,BOOST_PP_ADD(n,1))
2415 #define MSM_VISITOR_ARGS_TYPEDEF_SUB(z, n, unused) typename StateType::accept_sig::argument ## n
2416
2417 #define MSM_VISITOR_ARGS_EXECUTE(z, n, unused) \
2418 template <class StateType> \
2419 struct visitor_args<StateType,n> \
2420 { \
2421 template <class State> \
2422 static typename enable_if_c<!is_composite_state<State>::value,void >::type \
2423 helper (library_sm* sm, \
2424 int id,StateType& astate) \
2425 { \
2426 sm->m_visitors.insert(id, boost::bind(&StateType::accept, \
2427 ::boost::ref(astate) BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM(n, MSM_VISITOR_ARGS_SUB, ~) )); \
2428 } \
2429 template <class State> \
2430 static typename enable_if_c<is_composite_state<State>::value,void >::type \
2431 helper (library_sm* sm, \
2432 int id,StateType& astate) \
2433 { \
2434 void (StateType::*caccept)(BOOST_PP_ENUM(n, MSM_VISITOR_ARGS_TYPEDEF_SUB, ~ ) ) \
2435 = &StateType::composite_accept; \
2436 sm->m_visitors.insert(id, boost::bind(caccept, \
2437 ::boost::ref(astate) BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM(n, MSM_VISITOR_ARGS_SUB, ~) )); \
2438 } \
2439 };
2440 BOOST_PP_REPEAT(BOOST_PP_ADD(BOOST_MSM_VISITOR_ARG_SIZE,1), MSM_VISITOR_ARGS_EXECUTE, ~)
2441 #undef MSM_VISITOR_ARGS_EXECUTE
2442 #undef MSM_VISITOR_ARGS_SUB
2443
2444
2445
2446
2447 #if defined (__IBMCPP__) || (__GNUC__ == 4 && __GNUC_MINOR__ < 1) || (defined(_MSC_VER) && (_MSC_VER < 1400))
2448 public:
2449 #endif
2450 template<class ContainingSM>
2451 void set_containing_sm(ContainingSM* sm)
2452 {
2453 m_is_included=true;
2454 ::boost::fusion::for_each(m_substate_list,add_state<ContainingSM>(this,sm));
2455 }
2456 #if defined (__IBMCPP__) || (__GNUC__ == 4 && __GNUC_MINOR__ < 1) || (defined(_MSC_VER) && (_MSC_VER < 1400))
2457 private:
2458 #endif
2459
2460
2461 template<class ContainingSM>
2462 struct add_state
2463 {
2464 add_state(library_sm* self_,ContainingSM* sm)
2465 : self(self_),containing_sm(sm){}
2466
2467
2468 template <class StateType>
2469 typename ::boost::enable_if<
2470 typename is_composite_state<StateType>::type,void >::type
2471 new_state_helper(boost::msm::back::dummy<0> = 0) const
2472 {
2473 ::boost::fusion::at_key<StateType>(self->m_substate_list).set_containing_sm(containing_sm);
2474 }
2475
2476
2477 template <class StateType>
2478 typename ::boost::enable_if<
2479 typename boost::mpl::and_<typename boost::mpl::not_
2480 <typename is_composite_state<StateType>::type>::type,
2481 typename boost::mpl::not_
2482 <typename is_pseudo_exit<StateType>::type>::type
2483 >::type,void>::type
2484 new_state_helper( ::boost::msm::back::dummy<1> = 0) const
2485 {
2486
2487 }
2488
2489 template <class StateType>
2490 typename ::boost::enable_if<typename is_pseudo_exit<StateType>::type,void >::type
2491 new_state_helper( ::boost::msm::back::dummy<2> = 0) const
2492 {
2493 execute_return (ContainingSM::*pf) (typename StateType::event const& evt)=
2494 &ContainingSM::process_event;
2495 ::boost::function<execute_return (typename StateType::event const&)> fct =
2496 ::boost::bind(pf,containing_sm,::boost::placeholders::_1);
2497 ::boost::fusion::at_key<StateType>(self->m_substate_list).set_forward_fct(fct);
2498 }
2499
2500 template <class State>
2501 void operator()( State const&) const
2502 {
2503
2504 BOOST_STATIC_CONSTANT(int, state_id = (get_state_id<stt,State>::value));
2505
2506 this->new_state_helper<State>(),
2507 create_state_helper<State>::set_sm(self);
2508
2509 visitor_helper(state_id,::boost::fusion::at_key<State>(self->m_substate_list),
2510 ::boost::mpl::bool_<has_accept_sig<State>::type::value>());
2511 }
2512 private:
2513
2514 template <class StateType>
2515 void visitor_helper(int id,StateType& astate, ::boost::mpl::true_ const & ) const
2516 {
2517 visitor_args<StateType,StateType::accept_sig::args_number>::
2518 template helper<StateType>(self,id,astate);
2519 }
2520 template <class StateType>
2521 void visitor_helper(int ,StateType& , ::boost::mpl::false_ const &) const
2522 {
2523
2524 }
2525
2526 library_sm* self;
2527 ContainingSM* containing_sm;
2528 };
2529
2530
2531 struct copy_helper
2532 {
2533 copy_helper(library_sm* sm):
2534 m_sm(sm){}
2535 template <class StateType>
2536 void operator()( ::boost::msm::wrap<StateType> const& )
2537 {
2538 BOOST_STATIC_CONSTANT(int, state_id = (get_state_id<stt,StateType>::type::value));
2539
2540 visitor_helper<StateType>(state_id);
2541
2542
2543 create_state_helper<StateType>::set_sm(m_sm);
2544 }
2545 template <class StateType>
2546 typename ::boost::enable_if<typename has_accept_sig<StateType>::type,void >::type
2547 visitor_helper(int id) const
2548 {
2549 visitor_args<StateType,StateType::accept_sig::args_number>::template helper<StateType>
2550 (m_sm,id,::boost::fusion::at_key<StateType>(m_sm->m_substate_list));
2551 }
2552 template <class StateType>
2553 typename ::boost::disable_if<typename has_accept_sig<StateType>::type,void >::type
2554 visitor_helper(int) const
2555 {
2556
2557 }
2558
2559 library_sm* m_sm;
2560 };
2561
2562 template <class region_id,int Dummy=0>
2563 struct region_copy_helper
2564 {
2565 static void do_copy(library_sm* self_,library_sm const& rhs)
2566 {
2567 self_->m_states[region_id::value] = rhs.m_states[region_id::value];
2568 region_copy_helper< ::boost::mpl::int_<region_id::value+1> >::do_copy(self_,rhs);
2569 }
2570 };
2571 template <int Dummy>
2572 struct region_copy_helper< ::boost::mpl::int_<nr_regions::value>,Dummy>
2573 {
2574
2575 static void do_copy(library_sm*,library_sm const& ){}
2576 };
2577
2578 void do_copy (library_sm const& rhs,
2579 ::boost::msm::back::dummy<0> = 0)
2580 {
2581
2582 region_copy_helper< ::boost::mpl::int_<0> >::do_copy(this,rhs);
2583 m_events_queue = rhs.m_events_queue;
2584 m_deferred_events_queue = rhs.m_deferred_events_queue;
2585 m_history = rhs.m_history;
2586 m_event_processing = rhs.m_event_processing;
2587 m_is_included = rhs.m_is_included;
2588 m_substate_list = rhs.m_substate_list;
2589
2590
2591 ::boost::mpl::for_each<state_list, ::boost::msm::wrap< ::boost::mpl::placeholders::_1> >
2592 (copy_helper(this));
2593 }
2594
2595
2596
2597 template<class Event,bool is_entry>
2598 struct entry_exit_helper
2599 {
2600 entry_exit_helper(int id,Event const& e,library_sm* self_):
2601 state_id(id),evt(e),self(self_){}
2602
2603 template <class IsEntry,class State>
2604 typename ::boost::enable_if<typename IsEntry::type,void >::type
2605 helper( ::boost::msm::back::dummy<0> = 0)
2606 {
2607 BOOST_STATIC_CONSTANT(int, id = (get_state_id<stt,State>::value));
2608 if (id == state_id)
2609 {
2610 execute_entry<State>(::boost::fusion::at_key<State>(self->m_substate_list),evt,*self);
2611 }
2612 }
2613
2614 template <class IsEntry,class State>
2615 typename boost::disable_if<typename IsEntry::type,void >::type
2616 helper( ::boost::msm::back::dummy<1> = 0)
2617 {
2618 BOOST_STATIC_CONSTANT(int, id = (get_state_id<stt,State>::value));
2619 if (id == state_id)
2620 {
2621 execute_exit<State>(::boost::fusion::at_key<State>(self->m_substate_list),evt,*self);
2622 }
2623 }
2624
2625 template <class State>
2626 void operator()( ::boost::msm::wrap<State> const&)
2627 {
2628 entry_exit_helper<Event,is_entry>::template helper< ::boost::mpl::bool_<is_entry>,State >();
2629 }
2630 private:
2631 int state_id;
2632 Event const& evt;
2633 library_sm* self;
2634 };
2635
2636
2637 template <class region_id,int Dummy=0>
2638 struct region_start_helper
2639 {
2640 template<class Event>
2641 static void do_start(library_sm* self_,Event const& incomingEvent)
2642 {
2643
2644 ::boost::mpl::for_each<state_list, ::boost::msm::wrap< ::boost::mpl::placeholders::_1> >
2645 (entry_exit_helper<Event,true>(self_->m_states[region_id::value],incomingEvent,self_));
2646 region_start_helper
2647 < ::boost::mpl::int_<region_id::value+1> >::do_start(self_,incomingEvent);
2648 }
2649 };
2650 template <int Dummy>
2651 struct region_start_helper< ::boost::mpl::int_<nr_regions::value>,Dummy>
2652 {
2653
2654 template<class Event>
2655 static void do_start(library_sm*,Event const& ){}
2656 };
2657
2658 template <class Event>
2659 void internal_start(Event const& incomingEvent)
2660 {
2661 region_start_helper< ::boost::mpl::int_<0> >::do_start(this,incomingEvent);
2662
2663 handle_eventless_transitions_helper<library_sm> eventless_helper(this,true);
2664 eventless_helper.process_completion_event();
2665 }
2666
2667 template <class StateType>
2668 struct find_region_id
2669 {
2670 template <int region,int Dummy=0>
2671 struct In
2672 {
2673 enum {region_index=region};
2674 };
2675
2676 template<int Dummy>
2677 struct In<-1,Dummy>
2678 {
2679 typedef typename build_orthogonal_regions<
2680 library_sm,
2681 initial_states
2682 >::type all_regions;
2683 enum {region_index= find_region_index<all_regions,StateType>::value };
2684 };
2685 enum {region_index = In<StateType::zone_index>::region_index };
2686 };
2687
2688 struct direct_event_start_helper
2689 {
2690 direct_event_start_helper(library_sm* self_):self(self_){}
2691
2692 template <class EventType,class FsmType>
2693 typename ::boost::disable_if<typename has_direct_entry<EventType>::type,void>::type
2694 operator()(EventType const& evt,FsmType& fsm, ::boost::msm::back::dummy<0> = 0)
2695 {
2696 (static_cast<Derived*>(self))->on_entry(evt,fsm);
2697 self->internal_start(evt);
2698 }
2699
2700
2701 template <class EventType,class FsmType>
2702 typename ::boost::enable_if<
2703 typename ::boost::mpl::and_<
2704 typename ::boost::mpl::not_< typename is_pseudo_entry<
2705 typename EventType::active_state>::type >::type,
2706 typename ::boost::mpl::and_<typename has_direct_entry<EventType>::type,
2707 typename ::boost::mpl::not_<typename ::boost::mpl::is_sequence
2708 <typename EventType::active_state>::type >::type
2709 >::type>::type,void
2710 >::type
2711 operator()(EventType const& evt,FsmType& fsm, ::boost::msm::back::dummy<1> = 0)
2712 {
2713 (static_cast<Derived*>(self))->on_entry(evt,fsm);
2714 int state_id = get_state_id<stt,typename EventType::active_state::wrapped_entry>::value;
2715 BOOST_STATIC_ASSERT(find_region_id<typename EventType::active_state::wrapped_entry>::region_index >= 0);
2716 BOOST_STATIC_ASSERT(find_region_id<typename EventType::active_state::wrapped_entry>::region_index < nr_regions::value);
2717
2718 self->m_states[find_region_id<typename EventType::active_state::wrapped_entry>::region_index] = state_id;
2719 self->internal_start(evt.m_event);
2720 }
2721
2722
2723 template <class EventType,class FsmType>
2724 typename ::boost::enable_if<
2725 typename ::boost::mpl::and_<
2726 typename ::boost::mpl::not_<
2727 typename is_pseudo_entry<typename EventType::active_state>::type >::type,
2728 typename ::boost::mpl::and_<typename has_direct_entry<EventType>::type,
2729 typename ::boost::mpl::is_sequence<
2730 typename EventType::active_state>::type
2731 >::type>::type,void
2732 >::type
2733 operator()(EventType const& evt,FsmType& fsm, ::boost::msm::back::dummy<2> = 0)
2734 {
2735 (static_cast<Derived*>(self))->on_entry(evt,fsm);
2736 ::boost::mpl::for_each<typename EventType::active_state,
2737 ::boost::msm::wrap< ::boost::mpl::placeholders::_1> >
2738 (fork_helper<EventType>(self,evt));
2739
2740 self->internal_start(evt.m_event);
2741 }
2742
2743
2744 template <class EventType,class FsmType>
2745 typename ::boost::enable_if<
2746 typename is_pseudo_entry<typename EventType::active_state >::type,void
2747 >::type
2748 operator()(EventType const& evt,FsmType& fsm, ::boost::msm::back::dummy<3> = 0)
2749 {
2750
2751 (static_cast<Derived*>(self))->on_entry(evt,fsm);
2752 int state_id = get_state_id<stt,typename EventType::active_state::wrapped_entry>::value;
2753 BOOST_STATIC_ASSERT(find_region_id<typename EventType::active_state::wrapped_entry>::region_index >= 0);
2754 BOOST_STATIC_ASSERT(find_region_id<typename EventType::active_state::wrapped_entry>::region_index < nr_regions::value);
2755
2756 self->m_states[find_region_id<typename EventType::active_state::wrapped_entry>::region_index] = state_id;
2757 self->internal_start(evt.m_event);
2758
2759
2760 self->process_event(evt.m_event);
2761 }
2762 private:
2763
2764 library_sm* self;
2765 template <class EventType>
2766 struct fork_helper
2767 {
2768 fork_helper(library_sm* self_,EventType const& evt_):
2769 helper_self(self_),helper_evt(evt_){}
2770 template <class StateType>
2771 void operator()( ::boost::msm::wrap<StateType> const& )
2772 {
2773 int state_id = get_state_id<stt,typename StateType::wrapped_entry>::value;
2774 BOOST_STATIC_ASSERT(find_region_id<typename StateType::wrapped_entry>::region_index >= 0);
2775 BOOST_STATIC_ASSERT(find_region_id<typename StateType::wrapped_entry>::region_index < nr_regions::value);
2776 helper_self->m_states[find_region_id<typename StateType::wrapped_entry>::region_index] = state_id;
2777 }
2778 private:
2779 library_sm* helper_self;
2780 EventType const& helper_evt;
2781 };
2782 };
2783
2784
2785 template <class region_id,int Dummy=0>
2786 struct region_entry_exit_helper
2787 {
2788 template<class Event>
2789 static void do_entry(library_sm* self_,Event const& incomingEvent)
2790 {
2791 self_->m_states[region_id::value] =
2792 self_->m_history.history_entry(incomingEvent)[region_id::value];
2793 region_entry_exit_helper
2794 < ::boost::mpl::int_<region_id::value+1> >::do_entry(self_,incomingEvent);
2795 }
2796 template<class Event>
2797 static void do_exit(library_sm* self_,Event const& incomingEvent)
2798 {
2799 ::boost::mpl::for_each<state_list, ::boost::msm::wrap< ::boost::mpl::placeholders::_1> >
2800 (entry_exit_helper<Event,false>(self_->m_states[region_id::value],incomingEvent,self_));
2801 region_entry_exit_helper
2802 < ::boost::mpl::int_<region_id::value+1> >::do_exit(self_,incomingEvent);
2803 }
2804 };
2805 template <int Dummy>
2806 struct region_entry_exit_helper< ::boost::mpl::int_<nr_regions::value>,Dummy>
2807 {
2808
2809 template<class Event>
2810 static void do_entry(library_sm*,Event const& ){}
2811 template<class Event>
2812 static void do_exit(library_sm*,Event const& ){}
2813 };
2814
2815 template <class Event,class FsmType>
2816 void do_entry(Event const& incomingEvent,FsmType& fsm)
2817 {
2818
2819 region_entry_exit_helper< ::boost::mpl::int_<0> >::do_entry(this,incomingEvent);
2820
2821 m_event_processing = true;
2822
2823 direct_event_start_helper(this)(incomingEvent,fsm);
2824
2825 m_event_processing = false;
2826
2827 handle_defer_helper<library_sm> defer_helper(m_deferred_events_queue);
2828 defer_helper.do_handle_deferred(true);
2829 process_message_queue(this);
2830 }
2831 template <class Event,class FsmType>
2832 void do_exit(Event const& incomingEvent,FsmType& fsm)
2833 {
2834
2835
2836 region_entry_exit_helper< ::boost::mpl::int_<0> >::do_exit(this,incomingEvent);
2837
2838 (static_cast<Derived*>(this))->on_exit(incomingEvent,fsm);
2839
2840 m_history.history_exit(this->m_states);
2841
2842 if (!m_history.process_deferred_events(incomingEvent))
2843 {
2844 clear_deferred_queue();
2845 }
2846 }
2847
2848
2849 #if defined (__IBMCPP__) || (defined(_MSC_VER) && (_MSC_VER < 1400))
2850 public:
2851 #endif
2852
2853 template <class Event>
2854 static HandledEnum call_no_transition(library_sm& , int , int , Event const& )
2855 {
2856 return HANDLED_FALSE;
2857 }
2858
2859 template <class Event>
2860 static HandledEnum call_no_transition_internal(library_sm& , int , int , Event const& )
2861 {
2862
2863
2864 return HANDLED_FALSE;
2865 }
2866
2867 template <class Event>
2868 static HandledEnum defer_transition(library_sm& fsm, int , int , Event const& e)
2869 {
2870 fsm.defer_event(e);
2871 return HANDLED_DEFERRED;
2872 }
2873
2874
2875 template <class Event>
2876 static HandledEnum default_eventless_transition(library_sm&, int, int , Event const&)
2877 {
2878 return HANDLED_FALSE;
2879 }
2880 #if defined (__IBMCPP__) || (defined(_MSC_VER) && (_MSC_VER < 1400))
2881 private:
2882 #endif
2883
2884 template <class StateType>
2885 void process_message_queue(StateType*,
2886 typename ::boost::disable_if<typename is_no_message_queue<StateType>::type,void >::type* = 0)
2887 {
2888
2889 while (!m_events_queue.m_events_queue.empty())
2890 {
2891 transition_fct next = m_events_queue.m_events_queue.front();
2892 m_events_queue.m_events_queue.pop_front();
2893 next();
2894 }
2895 }
2896 template <class StateType>
2897 void process_message_queue(StateType*,
2898 typename ::boost::enable_if<typename is_no_message_queue<StateType>::type,void >::type* = 0)
2899 {
2900
2901 }
2902
2903
2904 template <class EventType>
2905 static
2906 typename boost::enable_if<typename has_direct_entry<EventType>::type,typename EventType::contained_event const& >::type
2907 remove_direct_entry_event_wrapper(EventType const& evt,boost::msm::back::dummy<0> = 0)
2908 {
2909 return evt.m_event;
2910 }
2911 template <class EventType>
2912 static typename boost::disable_if<typename has_direct_entry<EventType>::type,EventType const& >::type
2913 remove_direct_entry_event_wrapper(EventType const& evt,boost::msm::back::dummy<1> = 0)
2914 {
2915
2916 return evt;
2917 }
2918
2919
2920
2921 template <class StateType,class EventType,class FsmType>
2922 static
2923 typename boost::enable_if<typename is_composite_state<StateType>::type,void >::type
2924 execute_entry(StateType& astate,EventType const& evt,FsmType& fsm,boost::msm::back::dummy<0> = 0)
2925 {
2926
2927 astate.do_entry(evt,fsm);
2928 }
2929
2930 template <class StateType,class EventType,class FsmType>
2931 static
2932 typename ::boost::disable_if<
2933 typename ::boost::mpl::or_<typename is_composite_state<StateType>::type,
2934 typename is_pseudo_exit<StateType>::type >::type,void >::type
2935 execute_entry(StateType& astate,EventType const& evt,FsmType& fsm, ::boost::msm::back::dummy<1> = 0)
2936 {
2937
2938 astate.on_entry(remove_direct_entry_event_wrapper(evt),fsm);
2939 }
2940
2941 template <class StateType,class EventType,class FsmType>
2942 static
2943 typename ::boost::enable_if<typename is_pseudo_exit<StateType>::type,void >::type
2944 execute_entry(StateType& astate,EventType const& evt,FsmType& fsm, ::boost::msm::back::dummy<2> = 0)
2945 {
2946
2947
2948 astate.on_entry(evt,fsm);
2949 astate.forward_event(evt);
2950 }
2951 template <class StateType,class EventType,class FsmType>
2952 static
2953 typename ::boost::enable_if<typename is_composite_state<StateType>::type,void >::type
2954 execute_exit(StateType& astate,EventType const& evt,FsmType& fsm, ::boost::msm::back::dummy<0> = 0)
2955 {
2956 astate.do_exit(evt,fsm);
2957 }
2958 template <class StateType,class EventType,class FsmType>
2959 static
2960 typename ::boost::disable_if<typename is_composite_state<StateType>::type,void >::type
2961 execute_exit(StateType& astate,EventType const& evt,FsmType& fsm, ::boost::msm::back::dummy<1> = 0)
2962 {
2963
2964 astate.on_exit(evt,fsm);
2965 }
2966
2967
2968 template <class StateType,class TargetType,class EventType,class FsmType>
2969 static
2970 typename ::boost::disable_if<
2971 typename ::boost::mpl::or_<typename has_explicit_entry_state<TargetType>::type,
2972 ::boost::mpl::is_sequence<TargetType> >::type,void>::type
2973 convert_event_and_execute_entry(StateType& astate,EventType const& evt, FsmType& fsm, ::boost::msm::back::dummy<1> = 0)
2974 {
2975
2976 execute_entry<StateType>(astate,evt,fsm);
2977 }
2978 template <class StateType,class TargetType,class EventType,class FsmType>
2979 static
2980 typename ::boost::enable_if<
2981 typename ::boost::mpl::or_<typename has_explicit_entry_state<TargetType>::type,
2982 ::boost::mpl::is_sequence<TargetType> >::type,void >::type
2983 convert_event_and_execute_entry(StateType& astate,EventType const& evt, FsmType& fsm, ::boost::msm::back::dummy<0> = 0)
2984 {
2985
2986 execute_entry(astate,msm::back::direct_entry_event<TargetType,EventType>(evt),fsm);
2987 }
2988
2989
2990 template <class ContainingSM>
2991 void fill_states(ContainingSM* containing_sm=0)
2992 {
2993
2994 FsmCheckPolicy::template check_orthogonality<library_sm>();
2995
2996 FsmCheckPolicy::template check_unreachable_states<library_sm>();
2997
2998 BOOST_STATIC_CONSTANT(int, max_state = (mpl::size<state_list>::value));
2999
3000 m_visitors.fill_visitors(max_state);
3001 ::boost::fusion::for_each(m_substate_list,add_state<ContainingSM>(this,containing_sm));
3002
3003 }
3004
3005 private:
3006 template <class StateType,class Enable=void>
3007 struct msg_queue_helper
3008 {
3009 public:
3010 msg_queue_helper():m_events_queue(){}
3011 events_queue_t m_events_queue;
3012 };
3013 template <class StateType>
3014 struct msg_queue_helper<StateType,
3015 typename ::boost::enable_if<typename is_no_message_queue<StateType>::type >::type>
3016 {
3017 };
3018
3019 template <class Fsm,class Stt, class Event, class Compile>
3020 friend struct dispatch_table;
3021
3022
3023 int m_states[nr_regions::value];
3024 msg_queue_helper<library_sm> m_events_queue;
3025 deferred_msg_queue_helper
3026 <library_sm> m_deferred_events_queue;
3027 concrete_history m_history;
3028 bool m_event_processing;
3029 bool m_is_included;
3030 visitor_fct_helper<BaseState> m_visitors;
3031 substate_list m_substate_list;
3032
3033
3034 };
3035
3036 } } }
3037 #endif