Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 09:57:34

0001 // Copyright 2008 Christophe Henry
0002 // henry UNDERSCORE christophe AT hotmail DOT com
0003 // This is an extended version of the state machine available in the boost::mpl library
0004 // Distributed under the same license as the original.
0005 // Copyright for the original version:
0006 // Copyright 2005 David Abrahams and Aleksey Gurtovoy. Distributed
0007 // under the Boost Software License, Version 1.0. (See accompanying
0008 // file LICENSE_1_0.txt or copy at
0009 // http://www.boost.org/LICENSE_1_0.txt)
0010 
0011 #ifndef BOOST_MSM_BACK11_METAFUNCTIONS_H
0012 #define BOOST_MSM_BACK11_METAFUNCTIONS_H
0013 
0014 #include <algorithm>
0015 
0016 #include <boost/mpl/set.hpp>
0017 #include <boost/mpl/at.hpp>
0018 #include <boost/mpl/pair.hpp>
0019 #include <boost/mpl/map.hpp>
0020 #include <boost/mpl/int.hpp>
0021 #include <boost/mpl/has_xxx.hpp>
0022 #include <boost/mpl/find.hpp>
0023 #include <boost/mpl/count_if.hpp>
0024 #include <boost/mpl/fold.hpp>
0025 #include <boost/mpl/if.hpp>
0026 #include <boost/mpl/has_key.hpp>
0027 #include <boost/mpl/insert.hpp>
0028 #include <boost/mpl/next_prior.hpp>
0029 #include <boost/mpl/map.hpp>
0030 #include <boost/mpl/push_back.hpp>
0031 #include <boost/mpl/is_sequence.hpp>
0032 #include <boost/mpl/size.hpp>
0033 #include <boost/mpl/transform.hpp>
0034 #include <boost/mpl/begin_end.hpp>
0035 #include <boost/mpl/bool.hpp>
0036 #include <boost/mpl/empty.hpp>
0037 #include <boost/mpl/identity.hpp>
0038 #include <boost/mpl/eval_if.hpp>
0039 #include <boost/mpl/insert_range.hpp>
0040 #include <boost/mpl/front.hpp>
0041 #include <boost/mpl/logical.hpp>
0042 #include <boost/mpl/plus.hpp>
0043 #include <boost/mpl/copy_if.hpp>
0044 #include <boost/mpl/back_inserter.hpp>
0045 #include <boost/mpl/transform.hpp>
0046 
0047 #include <boost/fusion/include/mpl.hpp>
0048 #include <boost/fusion/container/vector/convert.hpp>
0049 #include <boost/fusion/include/as_vector.hpp>
0050 #include <boost/fusion/include/as_set.hpp>
0051 #include <boost/fusion/container/vector.hpp>
0052 #include <boost/fusion/include/set.hpp>
0053 #include <boost/fusion/include/map.hpp>
0054 #include <boost/fusion/include/pair.hpp>
0055 #include <boost/fusion/include/at_key.hpp>
0056 #include <boost/fusion/include/for_each.hpp>
0057 #include <boost/fusion/include/make_vector.hpp>
0058 #include <boost/fusion/include/has_key.hpp>
0059 #include <boost/fusion/include/make_set.hpp>
0060 #include <boost/fusion/include/value_at_key.hpp>
0061 #include <boost/fusion/include/front.hpp>
0062 
0063 #include <boost/type_traits/is_same.hpp>
0064 #include <boost/utility/enable_if.hpp>
0065 
0066 #include <boost/msm/row_tags.hpp>
0067 
0068 // mpl_graph graph implementation and depth first search
0069 #include <boost/msm/mpl_graph/incidence_list_graph.hpp>
0070 #include <boost/msm/mpl_graph/depth_first_search.hpp>
0071 
0072 BOOST_MPL_HAS_XXX_TRAIT_DEF(explicit_creation)
0073 BOOST_MPL_HAS_XXX_TRAIT_DEF(pseudo_entry)
0074 BOOST_MPL_HAS_XXX_TRAIT_DEF(pseudo_exit)
0075 BOOST_MPL_HAS_XXX_TRAIT_DEF(concrete_exit_state)
0076 BOOST_MPL_HAS_XXX_TRAIT_DEF(composite_tag)
0077 BOOST_MPL_HAS_XXX_TRAIT_DEF(not_real_row_tag)
0078 BOOST_MPL_HAS_XXX_TRAIT_DEF(event_blocking_flag)
0079 BOOST_MPL_HAS_XXX_TRAIT_DEF(explicit_entry_state)
0080 BOOST_MPL_HAS_XXX_TRAIT_DEF(completion_event)
0081 BOOST_MPL_HAS_XXX_TRAIT_DEF(no_exception_thrown)
0082 BOOST_MPL_HAS_XXX_TRAIT_DEF(no_message_queue)
0083 BOOST_MPL_HAS_XXX_TRAIT_DEF(activate_deferred_events)
0084 BOOST_MPL_HAS_XXX_TRAIT_DEF(wrapped_entry)
0085 BOOST_MPL_HAS_XXX_TRAIT_DEF(active_state_switch_policy)
0086 
0087 namespace boost { namespace msm { namespace back11
0088 {
0089 template <typename Sequence, typename Range>
0090 struct set_insert_range
0091 {
0092     typedef typename ::boost::mpl::fold<
0093         Range,Sequence, 
0094         ::boost::mpl::insert< ::boost::mpl::placeholders::_1, ::boost::mpl::placeholders::_2 >
0095     >::type type;
0096 };
0097 
0098 // returns the current state type of a transition
0099 template <class Transition>
0100 struct transition_source_type
0101 {
0102     typedef typename Transition::current_state_type type;
0103 };
0104 
0105 // returns the target state type of a transition
0106 template <class Transition>
0107 struct transition_target_type
0108 {
0109     typedef typename Transition::next_state_type type;
0110 };
0111 
0112 // helper functions for generate_state_ids
0113 // create a pair of a state and a passed id for source and target states
0114 template <class Id,class Transition>
0115 struct make_pair_source_state_id
0116 {
0117     typedef typename ::boost::fusion::pair<typename Transition::current_state_type,Id> type;
0118 };
0119 template <class Id,class Transition>
0120 struct make_pair_target_state_id
0121 {
0122     typedef typename ::boost::fusion::pair<typename Transition::next_state_type,Id> type;
0123 };
0124 // iterates through a transition table and automatically generates ids starting at 0
0125 // first the source states, transition up to down
0126 // then the target states, up to down
0127 template <class stt>
0128 struct generate_state_ids
0129 {
0130     typedef typename
0131         ::boost::mpl::fold<
0132         stt,::boost::mpl::pair< ::boost::fusion::map< >, ::boost::mpl::int_<0> >,
0133         ::boost::mpl::pair<
0134             ::boost::mpl::if_<
0135                      ::boost::mpl::has_key< ::boost::mpl::first< ::boost::mpl::placeholders::_1>,
0136                                             transition_source_type< ::boost::mpl::placeholders::_2> >,
0137                      ::boost::mpl::first< ::boost::mpl::placeholders::_1>,
0138                      boost::fusion::result_of::as_map<boost::fusion::result_of::insert<
0139                                 ::boost::mpl::first<mpl::placeholders::_1>,
0140                                 ::boost::fusion::result_of::end<::boost::mpl::first<mpl::placeholders::_1> >,
0141                                 make_pair_source_state_id< ::boost::mpl::second< ::boost::mpl::placeholders::_1 >,
0142                                                            ::boost::mpl::placeholders::_2> > >
0143                       >,
0144             ::boost::mpl::if_<
0145                     ::boost::mpl::has_key< ::boost::mpl::first< ::boost::mpl::placeholders::_1>,
0146                                            transition_source_type< ::boost::mpl::placeholders::_2> >,
0147                     ::boost::mpl::second< ::boost::mpl::placeholders::_1 >,
0148                     ::boost::mpl::next< ::boost::mpl::second<mpl::placeholders::_1 > >
0149                     >
0150         > //pair
0151         >::type source_state_ids;
0152 
0153     typedef typename ::boost::mpl::first<source_state_ids>::type source_state_map;
0154     typedef typename ::boost::mpl::second<source_state_ids>::type highest_state_id;
0155 
0156 
0157     typedef typename
0158         ::boost::mpl::fold<
0159         stt,::boost::mpl::pair< source_state_map, highest_state_id >,
0160         ::boost::mpl::pair<
0161             ::boost::mpl::if_<
0162                      ::boost::mpl::has_key< ::boost::mpl::first< ::boost::mpl::placeholders::_1>,
0163                                             transition_target_type< ::boost::mpl::placeholders::_2> >,
0164                      ::boost::mpl::first< ::boost::mpl::placeholders::_1>,
0165                      boost::fusion::result_of::as_map<boost::fusion::result_of::insert<
0166                                 ::boost::mpl::first<mpl::placeholders::_1>,
0167                                 ::boost::fusion::result_of::end<::boost::mpl::first<mpl::placeholders::_1> >,
0168                                 make_pair_target_state_id< ::boost::mpl::second< ::boost::mpl::placeholders::_1 >,
0169                                                            ::boost::mpl::placeholders::_2> > >
0170                       >,
0171             ::boost::mpl::if_<
0172                     ::boost::mpl::has_key< ::boost::mpl::first< ::boost::mpl::placeholders::_1>,
0173                                            transition_target_type< ::boost::mpl::placeholders::_2> >,
0174                     ::boost::mpl::second< ::boost::mpl::placeholders::_1 >,
0175                     ::boost::mpl::next< ::boost::mpl::second<mpl::placeholders::_1 > >
0176                     >
0177         > //pair
0178         >::type all_state_ids;
0179     typedef typename ::boost::mpl::first<all_state_ids>::type type;
0180 
0181 };
0182 
0183 template <class Fsm>
0184 struct get_active_state_switch_policy_helper
0185 {
0186     typedef typename Fsm::active_state_switch_policy type;
0187 };
0188 template <class Iter>
0189 struct get_active_state_switch_policy_helper2
0190 {
0191     typedef typename boost::mpl::deref<Iter>::type Fsm;
0192     typedef typename Fsm::active_state_switch_policy type;
0193 };
0194 // returns the active state switching policy
0195 template <class Fsm>
0196 struct get_active_state_switch_policy
0197 {
0198     typedef typename ::boost::mpl::find_if<
0199         typename Fsm::configuration,
0200         has_active_state_switch_policy< ::boost::mpl::placeholders::_1 > >::type iter;
0201 
0202     typedef typename ::boost::mpl::eval_if<
0203         typename ::boost::is_same<
0204             iter, 
0205             typename ::boost::mpl::end<typename Fsm::configuration>::type
0206         >::type,
0207         get_active_state_switch_policy_helper<Fsm>,
0208         get_active_state_switch_policy_helper2< iter >
0209     >::type type;
0210 };
0211 
0212 // returns the id of a given state
0213 template <class stt,class State>
0214 struct get_state_id
0215 {
0216     typedef typename ::boost::fusion::result_of::value_at_key<typename generate_state_ids<stt>::type,State>::type type;
0217     enum {value = type::value};
0218 };
0219 
0220 // returns a fusion::vector containing the init states of a state machine
0221 template <class States>
0222 struct get_initial_states 
0223 {
0224     typedef typename ::boost::mpl::if_<
0225         ::boost::mpl::is_sequence<States>,
0226         States,
0227         typename ::boost::mpl::push_back< ::boost::fusion::vector<>,States>::type >::type type;
0228 };
0229 // returns a mpl::int_ containing the size of a region. If the argument is not a sequence, returns 1
0230 template <class region>
0231 struct get_number_of_regions 
0232 {
0233     typedef typename mpl::if_<
0234         ::boost::mpl::is_sequence<region>,
0235         ::boost::mpl::size<region>,
0236         ::boost::mpl::int_<1> >::type type;
0237 };
0238 
0239 // builds a fusion::vector of initial states
0240 //TODO remove duplicate from get_initial_states
0241 template <class region>
0242 struct get_regions_as_sequence 
0243 {
0244     typedef typename ::boost::mpl::if_<
0245         ::boost::mpl::is_sequence<region>,
0246         region,
0247         typename ::boost::mpl::push_back< ::boost::fusion::vector0<>,region>::type >::type type;
0248 };
0249 
0250 template <class ToCreateSeq>
0251 struct get_explicit_creation_as_sequence 
0252 {
0253     typedef typename ::boost::mpl::if_<
0254         ::boost::mpl::is_sequence<ToCreateSeq>,
0255         ToCreateSeq,
0256         typename ::boost::mpl::push_back< ::boost::fusion::vector0<>,ToCreateSeq>::type >::type type;
0257 };
0258 
0259 // returns true if 2 transitions have the same source (used to remove duplicates in search of composite states)
0260 template <class stt,class Transition1,class Transition2>
0261 struct have_same_source
0262 {
0263     enum {current_state1 = get_state_id<stt,typename Transition1::current_state_type >::type::value};
0264     enum {current_state2 = get_state_id<stt,typename Transition2::current_state_type >::type::value};
0265     enum {value = ((int)current_state1 == (int)current_state2) };
0266 };
0267 
0268 
0269 // A metafunction that returns the Event associated with a transition.
0270 template <class Transition>
0271 struct transition_event
0272 {
0273     typedef typename Transition::transition_event type;
0274 };
0275 
0276 // returns true for composite states
0277 template <class State>
0278 struct is_composite_state
0279 {
0280     enum {value = has_composite_tag<State>::type::value};
0281     typedef typename has_composite_tag<State>::type type;
0282 };
0283 
0284 // transform a transition table in a container of source states
0285 template <class stt>
0286 struct keep_source_names
0287 {
0288     // instead of the rows we want only the names of the states (from source)
0289     typedef typename 
0290         ::boost::mpl::transform<
0291         stt,transition_source_type< ::boost::mpl::placeholders::_1> >::type type;
0292 };
0293 
0294 // transform a transition table in a container of target states
0295 template <class stt>
0296 struct keep_target_names
0297 {
0298     // instead of the rows we want only the names of the states (from source)
0299     typedef typename 
0300         ::boost::mpl::transform<
0301         stt,transition_target_type< ::boost::mpl::placeholders::_1> >::type type;
0302 };
0303 
0304 // fusion sets do not guarantee uniqueness so we need to check this before insertion
0305 template <class Set, class T>
0306 struct set_unique_insert
0307 {
0308     typedef typename ::boost::mpl::if_<
0309             ::boost::fusion::result_of::has_key<Set, T>,
0310             Set,
0311             typename ::boost::mpl::push_back<Set, T>::type
0312     >::type type;
0313 };
0314 
0315 template <class stt>
0316 struct generate_state_set
0317 {
0318     // keep in the original transition table only the source/target state types
0319     typedef typename keep_source_names<stt>::type sources;
0320     typedef typename keep_target_names<stt>::type targets;
0321 
0322     typedef typename
0323         ::boost::mpl::fold<
0324             sources,
0325             boost::fusion::set<>,
0326             boost::msm::back11::set_unique_insert< ::boost::mpl::placeholders::_1, ::boost::mpl::placeholders::_2>
0327         >::type source_set;
0328 
0329     typedef typename
0330         ::boost::mpl::fold<
0331             targets,
0332             source_set,
0333             boost::msm::back11::set_unique_insert< ::boost::mpl::placeholders::_1, ::boost::mpl::placeholders::_2>
0334         >::type type;
0335 };
0336 
0337 // iterates through the transition table and generate a fusion::set<> containing all the events
0338 template <class stt>
0339 struct generate_event_set
0340 {
0341     typedef typename 
0342         ::boost::mpl::fold<
0343             stt, ::boost::fusion::set<>,
0344             ::boost::mpl::if_<
0345                 ::boost::mpl::has_key< ::boost::mpl::placeholders::_1,
0346                                        transition_event< ::boost::mpl::placeholders::_2> >,
0347                 ::boost::mpl::placeholders::_1,
0348                 ::boost::mpl::push_back< ::boost::mpl::placeholders::_1,
0349                                          transition_event< ::boost::mpl::placeholders::_2> > >
0350         >::type type;
0351 };
0352 
0353 // returns a mpl::bool_<true> if State has Event as deferred event
0354 template <class State, class Event>
0355 struct has_state_delayed_event  
0356 {
0357     typedef typename ::boost::mpl::find<typename State::deferred_events,Event>::type found;
0358     typedef typename ::boost::mpl::if_<
0359         ::boost::is_same<found,typename ::boost::mpl::end<typename State::deferred_events>::type >,
0360         ::boost::mpl::bool_<false>,
0361         ::boost::mpl::bool_<true> >::type type;
0362 };
0363 // returns a mpl::bool_<true> if State has any deferred event
0364 template <class State>
0365 struct has_state_delayed_events  
0366 {
0367     typedef typename ::boost::mpl::if_<
0368         ::boost::mpl::empty<typename State::deferred_events>,
0369         ::boost::mpl::bool_<false>,
0370         ::boost::mpl::bool_<true> >::type type;
0371 };
0372 
0373 // Template used to create dummy entries for initial states not found in the stt.
0374 template< typename T1 >
0375 struct not_a_row
0376 {
0377     typedef int not_real_row_tag;
0378     struct dummy_event 
0379     {
0380     };
0381     typedef T1                  current_state_type;
0382     typedef T1                  next_state_type;
0383     typedef dummy_event         transition_event;
0384 };
0385 
0386 // metafunctions used to find out if a state is entry, exit or something else
0387 template <class State>
0388 struct is_pseudo_entry 
0389 {
0390     typedef typename ::boost::mpl::if_< typename has_pseudo_entry<State>::type,
0391         ::boost::mpl::bool_<true>,::boost::mpl::bool_<false> 
0392     >::type type;
0393 };
0394 // says if a state is an exit pseudo state
0395 template <class State>
0396 struct is_pseudo_exit 
0397 {
0398     typedef typename ::boost::mpl::if_< typename has_pseudo_exit<State>::type,
0399         ::boost::mpl::bool_<true>, ::boost::mpl::bool_<false> 
0400     >::type type;
0401 };
0402 // says if a state is an entry pseudo state or an explicit entry
0403 template <class State>
0404 struct is_direct_entry 
0405 {
0406     typedef typename ::boost::mpl::if_< typename has_explicit_entry_state<State>::type,
0407         ::boost::mpl::bool_<true>, ::boost::mpl::bool_<false> 
0408     >::type type;
0409 };
0410 
0411 //converts a "fake" (simulated in a state_machine_ description )state into one which will really get created
0412 template <class StateType,class CompositeType>
0413 struct convert_fake_state
0414 {
0415     // converts a state (explicit entry) into the state we really are going to create (explicit<>)
0416     typedef typename ::boost::mpl::if_<
0417         typename is_direct_entry<StateType>::type,
0418         typename CompositeType::template direct<StateType>,
0419         typename ::boost::mpl::identity<StateType>::type
0420     >::type type;
0421 };
0422 
0423 template <class StateType>
0424 struct get_explicit_creation 
0425 {
0426     typedef typename StateType::explicit_creation type;
0427 };
0428 
0429 template <class StateType>
0430 struct get_wrapped_entry 
0431 {
0432     typedef typename StateType::wrapped_entry type;
0433 };
0434 // used for states created with explicit_creation
0435 // if the state is an explicit entry, we reach for the wrapped state
0436 // otherwise, this returns the state itself
0437 template <class StateType>
0438 struct get_wrapped_state 
0439 {
0440     typedef typename ::boost::mpl::eval_if<
0441                 typename has_wrapped_entry<StateType>::type,
0442                 get_wrapped_entry<StateType>,
0443                 ::boost::mpl::identity<StateType> >::type type;
0444 };
0445 
0446 template <class Derived>
0447 struct create_stt 
0448 {
0449     //typedef typename Derived::transition_table stt;
0450     typedef typename Derived::real_transition_table Stt;
0451     // get the state set
0452     typedef typename generate_state_set<Stt>::type states;
0453     // transform the initial region(s) in a sequence
0454     typedef typename get_regions_as_sequence<typename Derived::initial_state>::type init_states;
0455     // iterate through the initial states and add them in the stt if not already there
0456     typedef typename 
0457         ::boost::mpl::fold<
0458         init_states,Stt,
0459         ::boost::mpl::if_<
0460                  ::boost::mpl::has_key<states, ::boost::mpl::placeholders::_2>,
0461                  ::boost::mpl::placeholders::_1,
0462                  ::boost::mpl::push_back< ::boost::mpl::placeholders::_1,
0463                              not_a_row< get_wrapped_state< ::boost::mpl::placeholders::_2> > > 
0464                   >
0465         >::type with_init;
0466     // do the same for states marked as explicitly created
0467     typedef typename get_explicit_creation_as_sequence<
0468        typename ::boost::mpl::eval_if<
0469             typename has_explicit_creation<Derived>::type,
0470             get_explicit_creation<Derived>,
0471             boost::fusion::result_of::make_vector<> >::type
0472         >::type fake_explicit_created;
0473 
0474     typedef typename 
0475         ::boost::mpl::transform<
0476         fake_explicit_created,convert_fake_state< ::boost::mpl::placeholders::_1,Derived> >::type explicit_created;
0477 
0478     typedef typename 
0479         ::boost::mpl::fold<
0480         explicit_created,with_init,
0481         ::boost::mpl::if_<
0482                  ::boost::mpl::has_key<states, ::boost::mpl::placeholders::_2>,
0483                  ::boost::mpl::placeholders::_1,
0484                  ::boost::mpl::push_back< ::boost::mpl::placeholders::_1,
0485                              not_a_row< get_wrapped_state< ::boost::mpl::placeholders::_2> > > 
0486                   >
0487         >::type type;
0488 };
0489 
0490 // returns the transition table of a Composite state
0491 template <class Composite>
0492 struct get_transition_table
0493 {
0494     typedef typename create_stt<Composite>::type type;
0495 };
0496 
0497 // recursively builds an internal table including those of substates, sub-substates etc.
0498 // variant for submachines
0499 template <class StateType,class IsComposite>
0500 struct recursive_get_internal_transition_table
0501 {
0502     // get the composite's internal table
0503     typedef typename StateType::internal_transition_table11 composite_table;
0504     // and for every substate (state of submachine), recursively get the internal transition table
0505     typedef typename generate_state_set<typename StateType::stt>::type composite_states;
0506     typedef typename ::boost::mpl::fold<
0507             composite_states, composite_table,
0508             ::boost::fusion::result_of::as_vector<
0509                 ::boost::fusion::result_of::insert_range<
0510                     ::boost::mpl::placeholders::_1,
0511                     ::boost::fusion::result_of::end< ::boost::mpl::placeholders::_1>,
0512                     recursive_get_internal_transition_table< ::boost::mpl::placeholders::_2, is_composite_state< ::boost::mpl::placeholders::_2> >
0513             >
0514          >
0515     >::type type;
0516 };
0517 // stop iterating on leafs (simple states)
0518 template <class StateType>
0519 struct recursive_get_internal_transition_table<StateType, ::boost::mpl::false_ >
0520 {
0521     typedef typename StateType::internal_transition_table11 type;
0522 };
0523 // recursively get a transition table for a given composite state.
0524 // returns the transition table for this state + the tables of all composite sub states recursively
0525 template <class Composite>
0526 struct recursive_get_transition_table
0527 {
0528     // get the transition table of the state if it's a state machine
0529     typedef typename ::boost::mpl::eval_if<typename is_composite_state<Composite>::type,
0530         get_transition_table<Composite>,
0531         boost::fusion::result_of::make_vector<>
0532     >::type org_table;
0533 
0534     typedef typename generate_state_set<org_table>::type states;
0535 
0536     // and for every substate, recursively get the transition table if it's a state machine
0537 //    typedef typename ::boost::mpl::fold<
0538 //        states,org_table,
0539 //        ::boost::mpl::insert_range< ::boost::mpl::placeholders::_1, ::boost::mpl::end<mpl::placeholders::_1>,
0540 //        recursive_get_transition_table< ::boost::mpl::placeholders::_2 > >
0541 //    >::type type;
0542     typedef typename ::boost::mpl::fold<
0543         states,org_table,
0544         ::boost::fusion::result_of::as_vector<
0545             ::boost::fusion::result_of::insert_range<
0546                 ::boost::mpl::placeholders::_1,
0547                 ::boost::fusion::result_of::end<mpl::placeholders::_1>,
0548                 recursive_get_transition_table< ::boost::mpl::placeholders::_2 >
0549             >
0550         >
0551     >::type type;
0552 };
0553 
0554 // metafunction used to say if a SM has pseudo exit states
0555 template <class Derived>
0556 struct has_fsm_deferred_events 
0557 {
0558     typedef typename create_stt<Derived>::type Stt;
0559     typedef typename generate_state_set<Stt>::type state_list;
0560 
0561     typedef typename ::boost::mpl::or_<
0562         typename has_activate_deferred_events<Derived>::type,
0563         ::boost::mpl::bool_< ::boost::mpl::count_if<
0564                 typename Derived::configuration,
0565                 has_activate_deferred_events< ::boost::mpl::placeholders::_1 > >::value != 0> 
0566     >::type found_in_fsm;
0567 
0568     typedef typename ::boost::mpl::or_<
0569             found_in_fsm,
0570             ::boost::mpl::bool_< ::boost::mpl::count_if<
0571                 state_list,has_state_delayed_events<
0572                     ::boost::mpl::placeholders::_1 > >::value != 0>
0573             >::type type;
0574 };
0575 
0576 // returns a mpl::bool_<true> if State has any delayed event
0577 template <class Event>
0578 struct is_completion_event  
0579 {
0580     typedef typename ::boost::mpl::if_<
0581         has_completion_event<Event>,
0582         ::boost::mpl::bool_<true>,
0583         ::boost::mpl::bool_<false> >::type type;
0584 };
0585 // metafunction used to say if a SM has eventless transitions
0586 template <class Derived>
0587 struct has_fsm_eventless_transition 
0588 {
0589     typedef typename create_stt<Derived>::type Stt;
0590     typedef typename generate_event_set<Stt>::type event_list;
0591 
0592     typedef ::boost::mpl::bool_< ::boost::mpl::count_if<
0593         event_list,is_completion_event< ::boost::mpl::placeholders::_1 > >::value != 0> type;
0594 };
0595 template <class Derived>
0596 struct find_completion_events 
0597 {
0598     typedef typename create_stt<Derived>::type Stt;
0599     typedef typename generate_event_set<Stt>::type event_list;
0600 
0601     typedef typename ::boost::mpl::fold<
0602         event_list, ::boost::fusion::set<>,
0603         ::boost::mpl::if_<
0604                  is_completion_event< ::boost::mpl::placeholders::_2>,
0605                  boost::msm::back11::set_unique_insert< ::boost::mpl::placeholders::_1, ::boost::mpl::placeholders::_2 >,
0606                  ::boost::mpl::placeholders::_1 >
0607     >::type type;
0608 };
0609 
0610 template <class Transition>
0611 struct make_vector 
0612 {
0613     typedef ::boost::fusion::vector<Transition> type;
0614 };
0615 template< typename Entry >
0616 struct get_first_element_pair_second
0617 {
0618     typedef typename ::boost::mpl::front<typename Entry::second>::type type;
0619 };
0620 template< typename Entry > 
0621 struct get_first_element_pair_second2
0622 { 
0623     //typedef typename ::boost::mpl::front<typename Entry::second>::type type;
0624     typedef typename ::boost::remove_reference<typename ::boost::fusion::result_of::front<
0625                 typename ::boost::fusion::result_of::second<Entry>::type >::type>::type type;
0626 }; 
0627 
0628  //returns the owner of an explicit_entry state
0629  //which is the containing SM if the transition originates from outside the containing SM
0630  //or else the explicit_entry state itself
0631 template <class State,class ContainingSM>
0632 struct get_owner 
0633 {
0634     typedef typename ::boost::mpl::if_<
0635         typename ::boost::mpl::not_<typename ::boost::is_same<typename State::owner,
0636                                                               ContainingSM >::type>::type,
0637         typename State::owner, 
0638         State >::type type;
0639 };
0640 
0641 template <class Sequence,class ContainingSM>
0642 struct get_fork_owner 
0643 {
0644     typedef typename ::boost::mpl::front<Sequence>::type seq_front;
0645     typedef typename ::boost::mpl::if_<
0646                     typename ::boost::mpl::not_<
0647                         typename ::boost::is_same<typename seq_front::owner,ContainingSM>::type>::type,
0648                     typename seq_front::owner, 
0649                     seq_front >::type type;
0650 };
0651 
0652 template <class StateType,class ContainingSM>
0653 struct make_exit 
0654 {
0655     typedef typename ::boost::mpl::if_<
0656              typename is_pseudo_exit<StateType>::type ,
0657              typename ContainingSM::template exit_pt<StateType>,
0658              typename ::boost::mpl::identity<StateType>::type
0659             >::type type;
0660 };
0661 
0662 template <class StateType,class ContainingSM>
0663 struct make_entry 
0664 {
0665     typedef typename ::boost::mpl::if_<
0666         typename is_pseudo_entry<StateType>::type ,
0667         typename ContainingSM::template entry_pt<StateType>,
0668         typename ::boost::mpl::if_<
0669                 typename is_direct_entry<StateType>::type,
0670                 typename ContainingSM::template direct<StateType>,
0671                 typename ::boost::mpl::identity<StateType>::type
0672                 >::type
0673         >::type type;
0674 };
0675 // metafunction used to say if a SM has pseudo exit states
0676 template <class StateType>
0677 struct has_exit_pseudo_states_helper 
0678 {
0679     typedef typename StateType::stt Stt;
0680     typedef typename generate_state_set<Stt>::type state_list;
0681 
0682     typedef ::boost::mpl::bool_< ::boost::mpl::count_if<
0683                 state_list,is_pseudo_exit< ::boost::mpl::placeholders::_1> >::value != 0> type;
0684 };
0685 template <class StateType>
0686 struct has_exit_pseudo_states 
0687 {
0688     typedef typename ::boost::mpl::eval_if<typename is_composite_state<StateType>::type,
0689         has_exit_pseudo_states_helper<StateType>,
0690         ::boost::mpl::bool_<false> >::type type;
0691 };
0692 
0693 // builds flags (add internal_flag_list and flag_list). internal_flag_list is used for terminate/interrupt states
0694 template <class StateType>
0695 struct get_flag_list 
0696 {
0697     typedef typename ::boost::fusion::result_of::as_vector<
0698         typename ::boost::fusion::result_of::insert_range<
0699             typename StateType::flag_list,
0700             typename ::boost::fusion::result_of::end< typename StateType::flag_list >::type,
0701             typename StateType::internal_flag_list
0702         >::type
0703     >::type type;
0704 };
0705 
0706 template <class StateType>
0707 struct is_state_blocking 
0708 {
0709     typedef typename ::boost::mpl::fold<
0710         typename get_flag_list<StateType>::type, ::boost::fusion::set<>,
0711         ::boost::mpl::if_<
0712                  has_event_blocking_flag< ::boost::mpl::placeholders::_2>,
0713                  boost::msm::back11::set_unique_insert< ::boost::mpl::placeholders::_1, ::boost::mpl::placeholders::_2 >,
0714                  ::boost::mpl::placeholders::_1 >
0715     >::type blocking_flags;
0716 
0717     typedef typename ::boost::mpl::if_<
0718         ::boost::mpl::empty<blocking_flags>,
0719         ::boost::mpl::bool_<false>,
0720         ::boost::mpl::bool_<true> >::type type;
0721 };
0722 // returns a mpl::bool_<true> if fsm has an event blocking flag in one of its substates
0723 template <class StateType>
0724 struct has_fsm_blocking_states  
0725 {
0726     typedef typename create_stt<StateType>::type Stt;
0727     typedef typename generate_state_set<Stt>::type state_list;
0728 
0729     typedef typename ::boost::mpl::fold<
0730         state_list, ::boost::fusion::set<>,
0731         ::boost::mpl::if_<
0732                  is_state_blocking< ::boost::mpl::placeholders::_2>,
0733                  ::boost::mpl::push_back< ::boost::mpl::placeholders::_1, ::boost::mpl::placeholders::_2 >,
0734                  ::boost::mpl::placeholders::_1 >
0735     >::type blocking_states;
0736 
0737     typedef typename ::boost::mpl::if_<
0738         ::boost::mpl::empty<blocking_states>,
0739         ::boost::mpl::bool_<false>,
0740         ::boost::mpl::bool_<true> >::type type;
0741 };
0742 
0743 template <class StateType>
0744 struct is_no_exception_thrown
0745 {
0746     typedef ::boost::mpl::bool_< ::boost::mpl::count_if<
0747         typename StateType::configuration,
0748         has_no_exception_thrown< ::boost::mpl::placeholders::_1 > >::value != 0> found;
0749 
0750     typedef typename ::boost::mpl::or_<
0751         typename has_no_exception_thrown<StateType>::type,
0752         found
0753     >::type type;
0754 };
0755 
0756 template <class StateType>
0757 struct is_no_message_queue
0758 {
0759     typedef ::boost::mpl::bool_< ::boost::mpl::count_if<
0760         typename StateType::configuration,
0761         has_no_message_queue< ::boost::mpl::placeholders::_1 > >::value != 0> found;
0762 
0763     typedef typename ::boost::mpl::or_<
0764         typename has_no_message_queue<StateType>::type,
0765         found
0766     >::type type;
0767 };
0768 
0769 template <class StateType>
0770 struct is_active_state_switch_policy 
0771 {
0772     typedef ::boost::mpl::bool_< ::boost::mpl::count_if<
0773         typename StateType::configuration,
0774         has_active_state_switch_policy< ::boost::mpl::placeholders::_1 > >::value != 0> found;
0775 
0776     typedef typename ::boost::mpl::or_<
0777         typename has_active_state_switch_policy<StateType>::type,
0778         found
0779     >::type type;
0780 };
0781 
0782 template <class StateType>
0783 struct get_initial_event 
0784 {
0785     typedef typename StateType::initial_event type;
0786 };
0787 
0788 template <class StateType>
0789 struct get_final_event 
0790 {
0791     typedef typename StateType::final_event type;
0792 };
0793 
0794 template <class TransitionTable, class InitState>
0795 struct build_one_orthogonal_region 
0796 {
0797      template<typename Row>
0798      struct row_to_incidence :
0799          ::boost::fusion::vector<
0800                 ::boost::mpl::pair<
0801                     typename Row::next_state_type, 
0802                     typename Row::transition_event>, 
0803                 typename Row::current_state_type, 
0804                 typename Row::next_state_type
0805          > {};
0806 
0807      template <class Seq, class Elt>
0808      struct transition_incidence_list_helper 
0809      {
0810          typedef typename ::boost::mpl::push_back< Seq, row_to_incidence< Elt > >::type type;
0811      };
0812 
0813      typedef typename ::boost::mpl::fold<
0814          TransitionTable,
0815          ::boost::fusion::vector<>,
0816          transition_incidence_list_helper< ::boost::mpl::placeholders::_1, ::boost::mpl::placeholders::_2>
0817      >::type transition_incidence_list;
0818 
0819      typedef ::boost::msm::mpl_graph::incidence_list_graph<transition_incidence_list>
0820          transition_graph;
0821 
0822      struct preordering_dfs_visitor : 
0823          ::boost::msm::mpl_graph::dfs_default_visitor_operations 
0824      {    
0825          template<typename Node, typename Graph, typename State>
0826          struct discover_vertex :
0827              ::boost::mpl::insert<State, Node>
0828          {};
0829      };
0830 
0831      typedef typename mpl::first< 
0832          typename ::boost::msm::mpl_graph::depth_first_search<
0833             transition_graph, 
0834             preordering_dfs_visitor,
0835             ::boost::fusion::set<>,
0836             InitState
0837          >::type
0838      >::type type;
0839 };
0840 
0841 template <class Fsm>
0842 struct find_entry_states 
0843 {
0844     typedef typename ::boost::mpl::copy<
0845         typename Fsm::substate_list,
0846         ::boost::mpl::inserter< 
0847             ::boost::fusion::set<>,
0848             ::boost::mpl::if_<
0849                 has_explicit_entry_state< ::boost::mpl::placeholders::_2 >,
0850                 boost::msm::back11::set_unique_insert< ::boost::mpl::placeholders::_1, ::boost::mpl::placeholders::_2>,
0851                 ::boost::mpl::placeholders::_1
0852             >
0853         >
0854     >::type type;
0855 };
0856 
0857 template <class Set1, class Set2>
0858 struct is_common_element 
0859 {
0860     typedef typename ::boost::mpl::fold<
0861         Set1, ::boost::mpl::false_,
0862         ::boost::mpl::if_<
0863             ::boost::mpl::has_key<
0864                 Set2,
0865                 ::boost::mpl::placeholders::_2
0866             >,
0867             ::boost::mpl::true_,
0868             ::boost::mpl::placeholders::_1
0869         >
0870     >::type type;
0871 };
0872 
0873 template <class EntryRegion, class AllRegions>
0874 struct add_entry_region 
0875 {
0876     typedef typename ::boost::mpl::transform<
0877         AllRegions, 
0878         ::boost::mpl::if_<
0879             is_common_element<EntryRegion, ::boost::mpl::placeholders::_1>,
0880             set_insert_range< ::boost::mpl::placeholders::_1, EntryRegion>,
0881             ::boost::mpl::placeholders::_1
0882         >
0883     >::type type;
0884 };
0885 
0886 // build a vector of regions states (as a set)
0887 // one set of states for every region
0888 template <class Fsm, class InitStates>
0889 struct build_orthogonal_regions 
0890 {
0891     typedef typename 
0892         ::boost::mpl::fold<
0893             InitStates, ::boost::fusion::vector0<>,
0894             ::boost::mpl::push_back< 
0895                 ::boost::mpl::placeholders::_1, 
0896                 build_one_orthogonal_region< typename Fsm::stt, ::boost::mpl::placeholders::_2 > >
0897         >::type without_entries;
0898 
0899     typedef typename 
0900         ::boost::mpl::fold<
0901         typename find_entry_states<Fsm>::type, ::boost::fusion::vector0<>,
0902             ::boost::mpl::push_back< 
0903                 ::boost::mpl::placeholders::_1, 
0904                 build_one_orthogonal_region< typename Fsm::stt, ::boost::mpl::placeholders::_2 > >
0905         >::type only_entries;
0906 
0907     typedef typename ::boost::mpl::fold<
0908         only_entries , without_entries,
0909         add_entry_region< ::boost::mpl::placeholders::_2, ::boost::mpl::placeholders::_1>
0910     >::type type;
0911 };
0912 
0913 template <class GraphAsSeqOfSets, class StateType>
0914 struct find_region_index
0915 {
0916     typedef typename 
0917         ::boost::mpl::fold<
0918             GraphAsSeqOfSets, ::boost::mpl::pair< ::boost::mpl::int_< -1 > /*res*/, ::boost::mpl::int_<0> /*counter*/ >,
0919             ::boost::mpl::if_<
0920                 ::boost::mpl::has_key< ::boost::mpl::placeholders::_2, StateType >,
0921                 ::boost::mpl::pair< 
0922                     ::boost::mpl::second< ::boost::mpl::placeholders::_1 >,
0923                     ::boost::mpl::next< ::boost::mpl::second< ::boost::mpl::placeholders::_1 > >
0924                 >,
0925                 ::boost::mpl::pair< 
0926                     ::boost::mpl::first< ::boost::mpl::placeholders::_1 >,
0927                     ::boost::mpl::next< ::boost::mpl::second< ::boost::mpl::placeholders::_1 > >
0928                 >
0929             >
0930         >::type result_pair;
0931     typedef typename ::boost::mpl::first<result_pair>::type type;
0932     enum {value = type::value};
0933 };
0934 
0935 template <class Fsm>
0936 struct check_regions_orthogonality
0937 {
0938     typedef typename build_orthogonal_regions< Fsm,typename Fsm::initial_states>::type regions;
0939     
0940     typedef typename ::boost::mpl::fold<
0941         regions, ::boost::mpl::int_<0>,
0942         ::boost::mpl::plus< ::boost::mpl::placeholders::_1 , ::boost::mpl::size< ::boost::mpl::placeholders::_2> >
0943     >::type number_of_states_in_regions;
0944 
0945     typedef typename ::boost::mpl::fold<
0946             regions,mpl::set0<>,
0947             set_insert_range< 
0948                     ::boost::mpl::placeholders::_1, 
0949                     ::boost::mpl::placeholders::_2 > 
0950     >::type one_big_states_set;
0951 
0952     enum {states_in_regions_raw = number_of_states_in_regions::value};
0953     enum {cumulated_states_in_regions_raw = ::boost::mpl::size<one_big_states_set>::value};
0954 };
0955 
0956 template <class Fsm>
0957 struct check_no_unreachable_state
0958 {
0959     typedef typename check_regions_orthogonality<Fsm>::one_big_states_set states_in_regions;
0960 
0961     typedef typename set_insert_range<
0962         states_in_regions, 
0963         typename ::boost::mpl::eval_if<
0964             typename has_explicit_creation<Fsm>::type,
0965             get_explicit_creation<Fsm>,
0966             ::boost::fusion::result_of::make_vector<>
0967         >::type
0968     >::type with_explicit_creation;
0969 
0970     enum {states_in_fsm = ::boost::mpl::size< typename Fsm::substate_list >::value};
0971     enum {cumulated_states_in_regions = ::boost::mpl::size< with_explicit_creation >::value};
0972 };
0973 
0974 // helper to find out if a SM has an active exit state and is therefore waiting for exiting
0975 template <class StateType,class OwnerFct,class FSM>
0976 inline
0977 typename ::boost::enable_if<typename ::boost::mpl::and_<typename is_composite_state<FSM>::type,
0978                                                         typename is_pseudo_exit<StateType>::type>,bool >::type
0979 is_exit_state_active(FSM& fsm)
0980 {
0981     typedef typename OwnerFct::type Composite;
0982     //typedef typename create_stt<Composite>::type stt;
0983     typedef typename Composite::stt stt;
0984     int state_id = get_state_id<stt,StateType>::type::value;
0985     Composite& comp = fsm.template get_state<Composite&>();
0986     return (std::find(comp.current_state(),comp.current_state()+Composite::nr_regions::value,state_id)
0987                             !=comp.current_state()+Composite::nr_regions::value);
0988 }
0989 template <class StateType,class OwnerFct,class FSM>
0990 inline
0991 typename ::boost::disable_if<typename ::boost::mpl::and_<typename is_composite_state<FSM>::type,
0992                                                          typename is_pseudo_exit<StateType>::type>,bool >::type
0993 is_exit_state_active(FSM&)
0994 {
0995     return false;
0996 }
0997 
0998 
0999 } } }//boost::msm::back11
1000 
1001 #endif // BOOST_MSM_BACK11_METAFUNCTIONS_H
1002