Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/boost/msm/back11/state_machine.hpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

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