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