Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:41:59

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