Back to home page

EIC code displayed by LXR

 
 

    


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

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