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