Chris@16: // Copyright 2008 Christophe Henry Chris@16: // henry UNDERSCORE christophe AT hotmail DOT com Chris@16: // This is an extended version of the state machine available in the boost::mpl library Chris@16: // Distributed under the same license as the original. Chris@16: // Copyright for the original version: Chris@16: // Copyright 2005 David Abrahams and Aleksey Gurtovoy. Distributed Chris@16: // under the Boost Software License, Version 1.0. (See accompanying Chris@16: // file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: #ifndef BOOST_MSM_BACK_METAFUNCTIONS_H Chris@16: #define BOOST_MSM_BACK_METAFUNCTIONS_H Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: Chris@16: // mpl_graph graph implementation and depth first search Chris@16: #include Chris@16: #include Chris@16: Chris@16: BOOST_MPL_HAS_XXX_TRAIT_DEF(explicit_creation) Chris@16: BOOST_MPL_HAS_XXX_TRAIT_DEF(pseudo_entry) Chris@16: BOOST_MPL_HAS_XXX_TRAIT_DEF(pseudo_exit) Chris@16: BOOST_MPL_HAS_XXX_TRAIT_DEF(concrete_exit_state) Chris@16: BOOST_MPL_HAS_XXX_TRAIT_DEF(composite_tag) Chris@16: BOOST_MPL_HAS_XXX_TRAIT_DEF(not_real_row_tag) Chris@16: BOOST_MPL_HAS_XXX_TRAIT_DEF(event_blocking_flag) Chris@16: BOOST_MPL_HAS_XXX_TRAIT_DEF(explicit_entry_state) Chris@16: BOOST_MPL_HAS_XXX_TRAIT_DEF(completion_event) Chris@16: BOOST_MPL_HAS_XXX_TRAIT_DEF(no_exception_thrown) Chris@16: BOOST_MPL_HAS_XXX_TRAIT_DEF(no_message_queue) Chris@16: BOOST_MPL_HAS_XXX_TRAIT_DEF(activate_deferred_events) Chris@16: BOOST_MPL_HAS_XXX_TRAIT_DEF(wrapped_entry) Chris@16: BOOST_MPL_HAS_XXX_TRAIT_DEF(active_state_switch_policy) Chris@16: Chris@16: namespace boost { namespace msm { namespace back Chris@16: { Chris@16: template Chris@16: struct set_insert_range Chris@16: { Chris@16: typedef typename ::boost::mpl::fold< Chris@16: Range,Sequence, Chris@16: ::boost::mpl::insert< ::boost::mpl::placeholders::_1, ::boost::mpl::placeholders::_2 > Chris@16: >::type type; Chris@16: }; Chris@16: Chris@16: // returns the current state type of a transition Chris@16: template Chris@16: struct transition_source_type Chris@16: { Chris@16: typedef typename Transition::current_state_type type; Chris@16: }; Chris@16: Chris@16: // returns the target state type of a transition Chris@16: template Chris@16: struct transition_target_type Chris@16: { Chris@16: typedef typename Transition::next_state_type type; Chris@16: }; Chris@16: Chris@16: // helper functions for generate_state_ids Chris@16: // create a pair of a state and a passed id for source and target states Chris@16: template Chris@16: struct make_pair_source_state_id Chris@16: { Chris@16: typedef typename ::boost::mpl::pair type; Chris@16: }; Chris@16: template Chris@16: struct make_pair_target_state_id Chris@16: { Chris@16: typedef typename ::boost::mpl::pair type; Chris@16: }; Chris@16: Chris@16: // iterates through a transition table and automatically generates ids starting at 0 Chris@16: // first the source states, transition up to down Chris@16: // then the target states, up to down Chris@16: template Chris@16: struct generate_state_ids Chris@16: { Chris@16: typedef typename Chris@16: ::boost::mpl::fold< Chris@16: stt,::boost::mpl::pair< ::boost::mpl::map< >, ::boost::mpl::int_<0> >, Chris@16: ::boost::mpl::pair< Chris@16: ::boost::mpl::if_< Chris@16: ::boost::mpl::has_key< ::boost::mpl::first< ::boost::mpl::placeholders::_1>, Chris@16: transition_source_type< ::boost::mpl::placeholders::_2> >, Chris@16: ::boost::mpl::first< ::boost::mpl::placeholders::_1>, Chris@16: ::boost::mpl::insert< ::boost::mpl::first, Chris@16: make_pair_source_state_id< ::boost::mpl::second< ::boost::mpl::placeholders::_1 >, Chris@16: ::boost::mpl::placeholders::_2> > Chris@16: >, Chris@16: ::boost::mpl::if_< Chris@16: ::boost::mpl::has_key< ::boost::mpl::first< ::boost::mpl::placeholders::_1>, Chris@16: transition_source_type< ::boost::mpl::placeholders::_2> >, Chris@16: ::boost::mpl::second< ::boost::mpl::placeholders::_1 >, Chris@16: ::boost::mpl::next< ::boost::mpl::second > Chris@16: > Chris@16: > //pair Chris@16: >::type source_state_ids; Chris@16: typedef typename ::boost::mpl::first::type source_state_map; Chris@16: typedef typename ::boost::mpl::second::type highest_state_id; Chris@16: Chris@16: Chris@16: typedef typename Chris@16: ::boost::mpl::fold< Chris@16: stt,::boost::mpl::pair, Chris@16: ::boost::mpl::pair< Chris@16: ::boost::mpl::if_< Chris@16: ::boost::mpl::has_key< ::boost::mpl::first< ::boost::mpl::placeholders::_1>, Chris@16: transition_target_type< ::boost::mpl::placeholders::_2> >, Chris@16: ::boost::mpl::first< ::boost::mpl::placeholders::_1>, Chris@16: ::boost::mpl::insert< ::boost::mpl::first< ::boost::mpl::placeholders::_1>, Chris@16: make_pair_target_state_id< ::boost::mpl::second< ::boost::mpl::placeholders::_1 >, Chris@16: ::boost::mpl::placeholders::_2> > Chris@16: >, Chris@16: ::boost::mpl::if_< Chris@16: ::boost::mpl::has_key< ::boost::mpl::first< ::boost::mpl::placeholders::_1>, Chris@16: transition_target_type< ::boost::mpl::placeholders::_2> >, Chris@16: ::boost::mpl::second< ::boost::mpl::placeholders::_1 >, Chris@16: ::boost::mpl::next< ::boost::mpl::second< ::boost::mpl::placeholders::_1 > > Chris@16: > Chris@16: > //pair Chris@16: >::type all_state_ids; Chris@16: typedef typename ::boost::mpl::first::type type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct get_active_state_switch_policy_helper Chris@16: { Chris@16: typedef typename Fsm::active_state_switch_policy type; Chris@16: }; Chris@16: template Chris@16: struct get_active_state_switch_policy_helper2 Chris@16: { Chris@16: typedef typename boost::mpl::deref::type Fsm; Chris@16: typedef typename Fsm::active_state_switch_policy type; Chris@16: }; Chris@16: // returns the active state switching policy Chris@16: template Chris@16: struct get_active_state_switch_policy Chris@16: { Chris@16: typedef typename ::boost::mpl::find_if< Chris@16: typename Fsm::configuration, Chris@16: has_active_state_switch_policy< ::boost::mpl::placeholders::_1 > >::type iter; Chris@16: Chris@16: typedef typename ::boost::mpl::eval_if< Chris@16: typename ::boost::is_same< Chris@16: iter, Chris@16: typename ::boost::mpl::end::type Chris@16: >::type, Chris@16: get_active_state_switch_policy_helper, Chris@16: get_active_state_switch_policy_helper2< iter > Chris@16: >::type type; Chris@16: }; Chris@16: Chris@16: // returns the id of a given state Chris@16: template Chris@16: struct get_state_id Chris@16: { Chris@16: typedef typename ::boost::mpl::at::type,State>::type type; Chris@16: enum {value = type::value}; Chris@16: }; Chris@16: Chris@16: // returns a mpl::vector containing the init states of a state machine Chris@16: template Chris@16: struct get_initial_states Chris@16: { Chris@16: typedef typename ::boost::mpl::if_< Chris@16: ::boost::mpl::is_sequence, Chris@16: States, Chris@16: typename ::boost::mpl::push_back< ::boost::mpl::vector0<>,States>::type >::type type; Chris@16: }; Chris@16: // returns a mpl::int_ containing the size of a region. If the argument is not a sequence, returns 1 Chris@16: template Chris@16: struct get_number_of_regions Chris@16: { Chris@16: typedef typename mpl::if_< Chris@16: ::boost::mpl::is_sequence, Chris@16: ::boost::mpl::size, Chris@16: ::boost::mpl::int_<1> >::type type; Chris@16: }; Chris@16: Chris@16: // builds a mpl::vector of initial states Chris@16: //TODO remove duplicate from get_initial_states Chris@16: template Chris@16: struct get_regions_as_sequence Chris@16: { Chris@16: typedef typename ::boost::mpl::if_< Chris@16: ::boost::mpl::is_sequence, Chris@16: region, Chris@16: typename ::boost::mpl::push_back< ::boost::mpl::vector0<>,region>::type >::type type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct get_explicit_creation_as_sequence Chris@16: { Chris@16: typedef typename ::boost::mpl::if_< Chris@16: ::boost::mpl::is_sequence, Chris@16: ToCreateSeq, Chris@16: typename ::boost::mpl::push_back< ::boost::mpl::vector0<>,ToCreateSeq>::type >::type type; Chris@16: }; Chris@16: Chris@16: // returns true if 2 transitions have the same source (used to remove duplicates in search of composite states) Chris@16: template Chris@16: struct have_same_source Chris@16: { Chris@16: enum {current_state1 = get_state_id::type::value}; Chris@16: enum {current_state2 = get_state_id::type::value}; Chris@16: enum {value = ((int)current_state1 == (int)current_state2) }; Chris@16: }; Chris@16: Chris@16: Chris@16: // A metafunction that returns the Event associated with a transition. Chris@16: template Chris@16: struct transition_event Chris@16: { Chris@16: typedef typename Transition::transition_event type; Chris@16: }; Chris@16: Chris@16: // returns true for composite states Chris@16: template Chris@16: struct is_composite_state Chris@16: { Chris@16: enum {value = has_composite_tag::type::value}; Chris@16: typedef typename has_composite_tag::type type; Chris@16: }; Chris@16: Chris@16: // transform a transition table in a container of source states Chris@16: template Chris@16: struct keep_source_names Chris@16: { Chris@16: // instead of the rows we want only the names of the states (from source) Chris@16: typedef typename Chris@16: ::boost::mpl::transform< Chris@16: stt,transition_source_type< ::boost::mpl::placeholders::_1> >::type type; Chris@16: }; Chris@16: Chris@16: // transform a transition table in a container of target states Chris@16: template Chris@16: struct keep_target_names Chris@16: { Chris@16: // instead of the rows we want only the names of the states (from source) Chris@16: typedef typename Chris@16: ::boost::mpl::transform< Chris@16: stt,transition_target_type< ::boost::mpl::placeholders::_1> >::type type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct generate_state_set Chris@16: { Chris@16: // keep in the original transition table only the source/target state types Chris@16: typedef typename keep_source_names::type sources; Chris@16: typedef typename keep_target_names::type targets; Chris@16: typedef typename Chris@16: ::boost::mpl::fold< Chris@16: sources, ::boost::mpl::set<>, Chris@16: ::boost::mpl::insert< ::boost::mpl::placeholders::_1, ::boost::mpl::placeholders::_2> Chris@16: >::type source_set; Chris@16: typedef typename Chris@16: ::boost::mpl::fold< Chris@16: targets,source_set, Chris@16: ::boost::mpl::insert< ::boost::mpl::placeholders::_1, ::boost::mpl::placeholders::_2> Chris@16: >::type type; Chris@16: }; Chris@16: Chris@16: // iterates through the transition table and generate a mpl::set<> containing all the events Chris@16: template Chris@16: struct generate_event_set Chris@16: { Chris@16: typedef typename Chris@16: ::boost::mpl::fold< Chris@16: stt, ::boost::mpl::set<>, Chris@16: ::boost::mpl::if_< Chris@16: ::boost::mpl::has_key< ::boost::mpl::placeholders::_1, Chris@16: transition_event< ::boost::mpl::placeholders::_2> >, Chris@16: ::boost::mpl::placeholders::_1, Chris@16: ::boost::mpl::insert< ::boost::mpl::placeholders::_1, Chris@16: transition_event< ::boost::mpl::placeholders::_2> > > Chris@16: >::type type; Chris@16: }; Chris@16: Chris@16: // returns a mpl::bool_ if State has Event as deferred event Chris@16: template Chris@16: struct has_state_delayed_event Chris@16: { Chris@16: typedef typename ::boost::mpl::find::type found; Chris@16: typedef typename ::boost::mpl::if_< Chris@16: ::boost::is_same::type >, Chris@16: ::boost::mpl::bool_, Chris@16: ::boost::mpl::bool_ >::type type; Chris@16: }; Chris@16: // returns a mpl::bool_ if State has any deferred event Chris@16: template Chris@16: struct has_state_delayed_events Chris@16: { Chris@16: typedef typename ::boost::mpl::if_< Chris@16: ::boost::mpl::empty, Chris@16: ::boost::mpl::bool_, Chris@16: ::boost::mpl::bool_ >::type type; Chris@16: }; Chris@16: Chris@16: // Template used to create dummy entries for initial states not found in the stt. Chris@16: template< typename T1 > Chris@16: struct not_a_row Chris@16: { Chris@16: typedef int not_real_row_tag; Chris@16: struct dummy_event Chris@16: { Chris@16: }; Chris@16: typedef T1 current_state_type; Chris@16: typedef T1 next_state_type; Chris@16: typedef dummy_event transition_event; Chris@16: }; Chris@16: Chris@16: // metafunctions used to find out if a state is entry, exit or something else Chris@16: template Chris@16: struct is_pseudo_entry Chris@16: { Chris@16: typedef typename ::boost::mpl::if_< typename has_pseudo_entry::type, Chris@16: ::boost::mpl::bool_,::boost::mpl::bool_ Chris@16: >::type type; Chris@16: }; Chris@16: // says if a state is an exit pseudo state Chris@16: template Chris@16: struct is_pseudo_exit Chris@16: { Chris@16: typedef typename ::boost::mpl::if_< typename has_pseudo_exit::type, Chris@16: ::boost::mpl::bool_, ::boost::mpl::bool_ Chris@16: >::type type; Chris@16: }; Chris@16: // says if a state is an entry pseudo state or an explicit entry Chris@16: template Chris@16: struct is_direct_entry Chris@16: { Chris@16: typedef typename ::boost::mpl::if_< typename has_explicit_entry_state::type, Chris@16: ::boost::mpl::bool_, ::boost::mpl::bool_ Chris@16: >::type type; Chris@16: }; Chris@16: Chris@16: //converts a "fake" (simulated in a state_machine_ description )state into one which will really get created Chris@16: template Chris@16: struct convert_fake_state Chris@16: { Chris@16: // converts a state (explicit entry) into the state we really are going to create (explicit<>) Chris@16: typedef typename ::boost::mpl::if_< Chris@16: typename is_direct_entry::type, Chris@16: typename CompositeType::template direct, Chris@16: typename ::boost::mpl::identity::type Chris@16: >::type type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct get_explicit_creation Chris@16: { Chris@16: typedef typename StateType::explicit_creation type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct get_wrapped_entry Chris@16: { Chris@16: typedef typename StateType::wrapped_entry type; Chris@16: }; Chris@16: // used for states created with explicit_creation Chris@16: // if the state is an explicit entry, we reach for the wrapped state Chris@16: // otherwise, this returns the state itself Chris@16: template Chris@16: struct get_wrapped_state Chris@16: { Chris@16: typedef typename ::boost::mpl::eval_if< Chris@16: typename has_wrapped_entry::type, Chris@16: get_wrapped_entry, Chris@16: ::boost::mpl::identity >::type type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct create_stt Chris@16: { Chris@16: //typedef typename Derived::transition_table stt; Chris@16: typedef typename Derived::real_transition_table Stt; Chris@16: // get the state set Chris@16: typedef typename generate_state_set::type states; Chris@16: // transform the initial region(s) in a sequence Chris@16: typedef typename get_regions_as_sequence::type init_states; Chris@16: // iterate through the initial states and add them in the stt if not already there Chris@16: typedef typename Chris@16: ::boost::mpl::fold< Chris@16: init_states,Stt, Chris@16: ::boost::mpl::if_< Chris@16: ::boost::mpl::has_key, Chris@16: ::boost::mpl::placeholders::_1, Chris@16: ::boost::mpl::insert< ::boost::mpl::placeholders::_1, ::boost::mpl::end< ::boost::mpl::placeholders::_1>, Chris@16: not_a_row< get_wrapped_state< ::boost::mpl::placeholders::_2> > > Chris@16: > Chris@16: >::type with_init; Chris@16: // do the same for states marked as explicitly created Chris@16: typedef typename get_explicit_creation_as_sequence< Chris@16: typename ::boost::mpl::eval_if< Chris@16: typename has_explicit_creation::type, Chris@16: get_explicit_creation, Chris@16: ::boost::mpl::vector0<> >::type Chris@16: >::type fake_explicit_created; Chris@16: Chris@16: typedef typename Chris@16: ::boost::mpl::transform< Chris@16: fake_explicit_created,convert_fake_state< ::boost::mpl::placeholders::_1,Derived> >::type explicit_created; Chris@16: Chris@16: typedef typename Chris@16: ::boost::mpl::fold< Chris@16: explicit_created,with_init, Chris@16: ::boost::mpl::if_< Chris@16: ::boost::mpl::has_key, Chris@16: ::boost::mpl::placeholders::_1, Chris@16: ::boost::mpl::insert< ::boost::mpl::placeholders::_1, ::boost::mpl::end, Chris@16: not_a_row< get_wrapped_state< ::boost::mpl::placeholders::_2> > > Chris@16: > Chris@16: >::type type; Chris@16: }; Chris@16: Chris@16: // returns the transition table of a Composite state Chris@16: template Chris@16: struct get_transition_table Chris@16: { Chris@16: typedef typename create_stt::type type; Chris@16: }; Chris@16: Chris@16: // recursively builds an internal table including those of substates, sub-substates etc. Chris@16: // variant for submachines Chris@16: template Chris@16: struct recursive_get_internal_transition_table Chris@16: { Chris@16: // get the composite's internal table Chris@16: typedef typename StateType::internal_transition_table composite_table; Chris@16: // and for every substate (state of submachine), recursively get the internal transition table Chris@16: typedef typename generate_state_set::type composite_states; Chris@16: typedef typename ::boost::mpl::fold< Chris@16: composite_states, composite_table, Chris@16: ::boost::mpl::insert_range< ::boost::mpl::placeholders::_1, ::boost::mpl::end< ::boost::mpl::placeholders::_1>, Chris@16: recursive_get_internal_transition_table< ::boost::mpl::placeholders::_2, is_composite_state< ::boost::mpl::placeholders::_2> > Chris@16: > Chris@16: >::type type; Chris@16: }; Chris@16: // stop iterating on leafs (simple states) Chris@16: template Chris@16: struct recursive_get_internal_transition_table Chris@16: { Chris@16: typedef typename StateType::internal_transition_table type; Chris@16: }; Chris@16: // recursively get a transition table for a given composite state. Chris@16: // returns the transition table for this state + the tables of all composite sub states recursively Chris@16: template Chris@16: struct recursive_get_transition_table Chris@16: { Chris@16: // get the transition table of the state if it's a state machine Chris@16: typedef typename ::boost::mpl::eval_if::type, Chris@16: get_transition_table, Chris@16: ::boost::mpl::vector0<> Chris@16: >::type org_table; Chris@16: Chris@16: typedef typename generate_state_set::type states; Chris@16: Chris@16: // and for every substate, recursively get the transition table if it's a state machine Chris@16: typedef typename ::boost::mpl::fold< Chris@16: states,org_table, Chris@16: ::boost::mpl::insert_range< ::boost::mpl::placeholders::_1, ::boost::mpl::end, Chris@16: recursive_get_transition_table< ::boost::mpl::placeholders::_2 > > Chris@16: >::type type; Chris@16: Chris@16: }; Chris@16: Chris@16: // metafunction used to say if a SM has pseudo exit states Chris@16: template Chris@16: struct has_fsm_deferred_events Chris@16: { Chris@16: typedef typename create_stt::type Stt; Chris@16: typedef typename generate_state_set::type state_list; Chris@16: Chris@16: typedef typename ::boost::mpl::or_< Chris@16: typename has_activate_deferred_events::type, Chris@16: ::boost::mpl::bool_< ::boost::mpl::count_if< Chris@16: typename Derived::configuration, Chris@16: has_activate_deferred_events< ::boost::mpl::placeholders::_1 > >::value != 0> Chris@16: >::type found_in_fsm; Chris@16: Chris@16: typedef typename ::boost::mpl::or_< Chris@16: found_in_fsm, Chris@16: ::boost::mpl::bool_< ::boost::mpl::count_if< Chris@16: state_list,has_state_delayed_events< Chris@16: ::boost::mpl::placeholders::_1 > >::value != 0> Chris@16: >::type type; Chris@16: }; Chris@16: Chris@16: // returns a mpl::bool_ if State has any delayed event Chris@16: template Chris@16: struct is_completion_event Chris@16: { Chris@16: typedef typename ::boost::mpl::if_< Chris@16: has_completion_event, Chris@16: ::boost::mpl::bool_, Chris@16: ::boost::mpl::bool_ >::type type; Chris@16: }; Chris@16: // metafunction used to say if a SM has eventless transitions Chris@16: template Chris@16: struct has_fsm_eventless_transition Chris@16: { Chris@16: typedef typename create_stt::type Stt; Chris@16: typedef typename generate_event_set::type event_list; Chris@16: Chris@16: typedef ::boost::mpl::bool_< ::boost::mpl::count_if< Chris@16: event_list,is_completion_event< ::boost::mpl::placeholders::_1 > >::value != 0> type; Chris@16: }; Chris@16: template Chris@16: struct find_completion_events Chris@16: { Chris@16: typedef typename create_stt::type Stt; Chris@16: typedef typename generate_event_set::type event_list; Chris@16: Chris@16: typedef typename ::boost::mpl::fold< Chris@16: event_list, ::boost::mpl::set<>, Chris@16: ::boost::mpl::if_< Chris@16: is_completion_event< ::boost::mpl::placeholders::_2>, Chris@16: ::boost::mpl::insert< ::boost::mpl::placeholders::_1, ::boost::mpl::placeholders::_2 >, Chris@16: ::boost::mpl::placeholders::_1 > Chris@16: >::type type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct make_vector Chris@16: { Chris@16: typedef ::boost::mpl::vector type; Chris@16: }; Chris@16: template< typename Entry > Chris@16: struct get_first_element_pair_second Chris@16: { Chris@16: typedef typename ::boost::mpl::front::type type; Chris@16: }; Chris@16: Chris@16: //returns the owner of an explicit_entry state Chris@16: //which is the containing SM if the transition originates from outside the containing SM Chris@16: //or else the explicit_entry state itself Chris@16: template Chris@16: struct get_owner Chris@16: { Chris@16: typedef typename ::boost::mpl::if_< Chris@16: typename ::boost::mpl::not_::type>::type, Chris@16: typename State::owner, Chris@16: State >::type type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct get_fork_owner Chris@16: { Chris@16: typedef typename ::boost::mpl::front::type seq_front; Chris@16: typedef typename ::boost::mpl::if_< Chris@16: typename ::boost::mpl::not_< Chris@16: typename ::boost::is_same::type>::type, Chris@16: typename seq_front::owner, Chris@16: seq_front >::type type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct make_exit Chris@16: { Chris@16: typedef typename ::boost::mpl::if_< Chris@16: typename is_pseudo_exit::type , Chris@16: typename ContainingSM::template exit_pt, Chris@16: typename ::boost::mpl::identity::type Chris@16: >::type type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct make_entry Chris@16: { Chris@16: typedef typename ::boost::mpl::if_< Chris@16: typename is_pseudo_entry::type , Chris@16: typename ContainingSM::template entry_pt, Chris@16: typename ::boost::mpl::if_< Chris@16: typename is_direct_entry::type, Chris@16: typename ContainingSM::template direct, Chris@16: typename ::boost::mpl::identity::type Chris@16: >::type Chris@16: >::type type; Chris@16: }; Chris@16: // metafunction used to say if a SM has pseudo exit states Chris@16: template Chris@16: struct has_exit_pseudo_states_helper Chris@16: { Chris@16: typedef typename StateType::stt Stt; Chris@16: typedef typename generate_state_set::type state_list; Chris@16: Chris@16: typedef ::boost::mpl::bool_< ::boost::mpl::count_if< Chris@16: state_list,is_pseudo_exit< ::boost::mpl::placeholders::_1> >::value != 0> type; Chris@16: }; Chris@16: template Chris@16: struct has_exit_pseudo_states Chris@16: { Chris@16: typedef typename ::boost::mpl::eval_if::type, Chris@16: has_exit_pseudo_states_helper, Chris@16: ::boost::mpl::bool_ >::type type; Chris@16: }; Chris@16: Chris@16: // builds flags (add internal_flag_list and flag_list). internal_flag_list is used for terminate/interrupt states Chris@16: template Chris@16: struct get_flag_list Chris@16: { Chris@16: typedef typename ::boost::mpl::insert_range< Chris@16: typename StateType::flag_list, Chris@16: typename ::boost::mpl::end< typename StateType::flag_list >::type, Chris@16: typename StateType::internal_flag_list Chris@16: >::type type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct is_state_blocking Chris@16: { Chris@16: typedef typename ::boost::mpl::fold< Chris@16: typename get_flag_list::type, ::boost::mpl::set<>, Chris@16: ::boost::mpl::if_< Chris@16: has_event_blocking_flag< ::boost::mpl::placeholders::_2>, Chris@16: ::boost::mpl::insert< ::boost::mpl::placeholders::_1, ::boost::mpl::placeholders::_2 >, Chris@16: ::boost::mpl::placeholders::_1 > Chris@16: >::type blocking_flags; Chris@16: Chris@16: typedef typename ::boost::mpl::if_< Chris@16: ::boost::mpl::empty, Chris@16: ::boost::mpl::bool_, Chris@16: ::boost::mpl::bool_ >::type type; Chris@16: }; Chris@16: // returns a mpl::bool_ if fsm has an event blocking flag in one of its substates Chris@16: template Chris@16: struct has_fsm_blocking_states Chris@16: { Chris@16: typedef typename create_stt::type Stt; Chris@16: typedef typename generate_state_set::type state_list; Chris@16: Chris@16: typedef typename ::boost::mpl::fold< Chris@16: state_list, ::boost::mpl::set<>, Chris@16: ::boost::mpl::if_< Chris@16: is_state_blocking< ::boost::mpl::placeholders::_2>, Chris@16: ::boost::mpl::insert< ::boost::mpl::placeholders::_1, ::boost::mpl::placeholders::_2 >, Chris@16: ::boost::mpl::placeholders::_1 > Chris@16: >::type blocking_states; Chris@16: Chris@16: typedef typename ::boost::mpl::if_< Chris@16: ::boost::mpl::empty, Chris@16: ::boost::mpl::bool_, Chris@16: ::boost::mpl::bool_ >::type type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct is_no_exception_thrown Chris@16: { Chris@16: typedef ::boost::mpl::bool_< ::boost::mpl::count_if< Chris@16: typename StateType::configuration, Chris@16: has_no_exception_thrown< ::boost::mpl::placeholders::_1 > >::value != 0> found; Chris@16: Chris@16: typedef typename ::boost::mpl::or_< Chris@16: typename has_no_exception_thrown::type, Chris@16: found Chris@16: >::type type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct is_no_message_queue Chris@16: { Chris@16: typedef ::boost::mpl::bool_< ::boost::mpl::count_if< Chris@16: typename StateType::configuration, Chris@16: has_no_message_queue< ::boost::mpl::placeholders::_1 > >::value != 0> found; Chris@16: Chris@16: typedef typename ::boost::mpl::or_< Chris@16: typename has_no_message_queue::type, Chris@16: found Chris@16: >::type type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct is_active_state_switch_policy Chris@16: { Chris@16: typedef ::boost::mpl::bool_< ::boost::mpl::count_if< Chris@16: typename StateType::configuration, Chris@16: has_active_state_switch_policy< ::boost::mpl::placeholders::_1 > >::value != 0> found; Chris@16: Chris@16: typedef typename ::boost::mpl::or_< Chris@16: typename has_active_state_switch_policy::type, Chris@16: found Chris@16: >::type type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct get_initial_event Chris@16: { Chris@16: typedef typename StateType::initial_event type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct get_final_event Chris@16: { Chris@16: typedef typename StateType::final_event type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct build_one_orthogonal_region Chris@16: { Chris@16: template Chris@16: struct row_to_incidence : Chris@16: ::boost::mpl::vector< Chris@16: ::boost::mpl::pair< Chris@16: typename Row::next_state_type, Chris@16: typename Row::transition_event>, Chris@16: typename Row::current_state_type, Chris@16: typename Row::next_state_type Chris@16: > {}; Chris@16: Chris@16: template Chris@16: struct transition_incidence_list_helper Chris@16: { Chris@16: typedef typename ::boost::mpl::push_back< Seq, row_to_incidence< Elt > >::type type; Chris@16: }; Chris@16: Chris@16: typedef typename ::boost::mpl::fold< Chris@16: TransitionTable, Chris@16: ::boost::mpl::vector<>, Chris@16: transition_incidence_list_helper< ::boost::mpl::placeholders::_1, ::boost::mpl::placeholders::_2> Chris@16: >::type transition_incidence_list; Chris@16: Chris@16: typedef ::boost::msm::mpl_graph::incidence_list_graph Chris@16: transition_graph; Chris@16: Chris@16: struct preordering_dfs_visitor : Chris@16: ::boost::msm::mpl_graph::dfs_default_visitor_operations Chris@16: { Chris@16: template Chris@16: struct discover_vertex : Chris@16: ::boost::mpl::insert Chris@16: {}; Chris@16: }; Chris@16: Chris@16: typedef typename mpl::first< Chris@16: typename ::boost::msm::mpl_graph::depth_first_search< Chris@16: transition_graph, Chris@16: preordering_dfs_visitor, Chris@16: ::boost::mpl::set<>, Chris@16: InitState Chris@16: >::type Chris@16: >::type type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct find_entry_states Chris@16: { Chris@16: typedef typename ::boost::mpl::copy< Chris@16: typename Fsm::substate_list, Chris@16: ::boost::mpl::inserter< Chris@16: ::boost::mpl::set0<>, Chris@16: ::boost::mpl::if_< Chris@16: has_explicit_entry_state< ::boost::mpl::placeholders::_2 >, Chris@16: ::boost::mpl::insert< ::boost::mpl::placeholders::_1, ::boost::mpl::placeholders::_2>, Chris@16: ::boost::mpl::placeholders::_1 Chris@16: > Chris@16: > Chris@16: >::type type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct is_common_element Chris@16: { Chris@16: typedef typename ::boost::mpl::fold< Chris@16: Set1, ::boost::mpl::false_, Chris@16: ::boost::mpl::if_< Chris@16: ::boost::mpl::has_key< Chris@16: Set2, Chris@16: ::boost::mpl::placeholders::_2 Chris@16: >, Chris@16: ::boost::mpl::true_, Chris@16: ::boost::mpl::placeholders::_1 Chris@16: > Chris@16: >::type type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct add_entry_region Chris@16: { Chris@16: typedef typename ::boost::mpl::transform< Chris@16: AllRegions, Chris@16: ::boost::mpl::if_< Chris@16: is_common_element, Chris@16: set_insert_range< ::boost::mpl::placeholders::_1, EntryRegion>, Chris@16: ::boost::mpl::placeholders::_1 Chris@16: > Chris@16: >::type type; Chris@16: }; Chris@16: Chris@16: // build a vector of regions states (as a set) Chris@16: // one set of states for every region Chris@16: template Chris@16: struct build_orthogonal_regions Chris@16: { Chris@16: typedef typename Chris@16: ::boost::mpl::fold< Chris@16: InitStates, ::boost::mpl::vector0<>, Chris@16: ::boost::mpl::push_back< Chris@16: ::boost::mpl::placeholders::_1, Chris@16: build_one_orthogonal_region< typename Fsm::stt, ::boost::mpl::placeholders::_2 > > Chris@16: >::type without_entries; Chris@16: Chris@16: typedef typename Chris@16: ::boost::mpl::fold< Chris@16: typename find_entry_states::type, ::boost::mpl::vector0<>, Chris@16: ::boost::mpl::push_back< Chris@16: ::boost::mpl::placeholders::_1, Chris@16: build_one_orthogonal_region< typename Fsm::stt, ::boost::mpl::placeholders::_2 > > Chris@16: >::type only_entries; Chris@16: Chris@16: typedef typename ::boost::mpl::fold< Chris@16: only_entries , without_entries, Chris@16: add_entry_region< ::boost::mpl::placeholders::_2, ::boost::mpl::placeholders::_1> Chris@16: >::type type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct find_region_index Chris@16: { Chris@16: typedef typename Chris@16: ::boost::mpl::fold< Chris@16: GraphAsSeqOfSets, ::boost::mpl::pair< ::boost::mpl::int_< -1 > /*res*/, ::boost::mpl::int_<0> /*counter*/ >, Chris@16: ::boost::mpl::if_< Chris@16: ::boost::mpl::has_key< ::boost::mpl::placeholders::_2, StateType >, Chris@16: ::boost::mpl::pair< Chris@16: ::boost::mpl::second< ::boost::mpl::placeholders::_1 >, Chris@16: ::boost::mpl::next< ::boost::mpl::second< ::boost::mpl::placeholders::_1 > > Chris@16: >, Chris@16: ::boost::mpl::pair< Chris@16: ::boost::mpl::first< ::boost::mpl::placeholders::_1 >, Chris@16: ::boost::mpl::next< ::boost::mpl::second< ::boost::mpl::placeholders::_1 > > Chris@16: > Chris@16: > Chris@16: >::type result_pair; Chris@16: typedef typename ::boost::mpl::first::type type; Chris@16: enum {value = type::value}; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct check_regions_orthogonality Chris@16: { Chris@16: typedef typename build_orthogonal_regions< Fsm,typename Fsm::initial_states>::type regions; Chris@16: Chris@16: typedef typename ::boost::mpl::fold< Chris@16: regions, ::boost::mpl::int_<0>, Chris@16: ::boost::mpl::plus< ::boost::mpl::placeholders::_1 , ::boost::mpl::size< ::boost::mpl::placeholders::_2> > Chris@16: >::type number_of_states_in_regions; Chris@16: Chris@16: typedef typename ::boost::mpl::fold< Chris@16: regions,mpl::set0<>, Chris@16: set_insert_range< Chris@16: ::boost::mpl::placeholders::_1, Chris@16: ::boost::mpl::placeholders::_2 > Chris@16: >::type one_big_states_set; Chris@16: Chris@16: enum {states_in_regions_raw = number_of_states_in_regions::value}; Chris@16: enum {cumulated_states_in_regions_raw = ::boost::mpl::size::value}; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct check_no_unreachable_state Chris@16: { Chris@16: typedef typename check_regions_orthogonality::one_big_states_set states_in_regions; Chris@16: Chris@16: typedef typename set_insert_range< Chris@16: states_in_regions, Chris@16: typename ::boost::mpl::eval_if< Chris@16: typename has_explicit_creation::type, Chris@16: get_explicit_creation, Chris@16: ::boost::mpl::vector0<> Chris@16: >::type Chris@16: >::type with_explicit_creation; Chris@16: Chris@16: enum {states_in_fsm = ::boost::mpl::size< typename Fsm::substate_list >::value}; Chris@16: enum {cumulated_states_in_regions = ::boost::mpl::size< with_explicit_creation >::value}; Chris@16: }; Chris@16: Chris@16: // helper to find out if a SM has an active exit state and is therefore waiting for exiting Chris@16: template Chris@16: inline Chris@16: typename ::boost::enable_if::type, Chris@16: typename is_pseudo_exit::type>,bool >::type Chris@16: is_exit_state_active(FSM& fsm) Chris@16: { Chris@16: typedef typename OwnerFct::type Composite; Chris@16: //typedef typename create_stt::type stt; Chris@16: typedef typename Composite::stt stt; Chris@16: int state_id = get_state_id::type::value; Chris@16: Composite& comp = fsm.template get_state(); Chris@16: return (std::find(comp.current_state(),comp.current_state()+Composite::nr_regions::value,state_id) Chris@16: !=comp.current_state()+Composite::nr_regions::value); Chris@16: } Chris@16: template Chris@16: inline Chris@16: typename ::boost::disable_if::type, Chris@16: typename is_pseudo_exit::type>,bool >::type Chris@16: is_exit_state_active(FSM&) Chris@16: { Chris@16: return false; Chris@16: } Chris@16: Chris@16: // transformation metafunction to end interrupt flags Chris@16: template Chris@16: struct transform_to_end_interrupt Chris@16: { Chris@16: typedef boost::msm::EndInterruptFlag type; Chris@16: }; Chris@16: // transform a sequence of events into another one of EndInterruptFlag Chris@16: template Chris@16: struct apply_end_interrupt_flag Chris@16: { Chris@16: typedef typename Chris@16: ::boost::mpl::transform< Chris@16: Events,transform_to_end_interrupt< ::boost::mpl::placeholders::_1> >::type type; Chris@16: }; Chris@16: // returns a mpl vector containing all end interrupt events if sequence, otherwise the same event Chris@16: template Chris@16: struct get_interrupt_events Chris@16: { Chris@16: typedef typename ::boost::mpl::eval_if< Chris@16: ::boost::mpl::is_sequence, Chris@16: boost::msm::back::apply_end_interrupt_flag, Chris@16: boost::mpl::vector1 > >::type type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct build_interrupt_state_flag_list Chris@16: { Chris@16: typedef ::boost::mpl::vector first_part; Chris@16: typedef typename ::boost::mpl::insert_range< Chris@16: first_part, Chris@16: typename ::boost::mpl::end< first_part >::type, Chris@16: Events Chris@16: >::type type; Chris@16: }; Chris@16: Chris@16: } } }//boost::msm::back Chris@16: Chris@16: #endif // BOOST_MSM_BACK_METAFUNCTIONS_H Chris@16: