PageRenderTime 83ms CodeModel.GetById 8ms app.highlight 66ms RepoModel.GetById 1ms app.codeStats 1ms

/Src/Dependencies/Boost/boost/msm/back/metafunctions.hpp

http://hadesmem.googlecode.com/
C++ Header | 906 lines | 753 code | 88 blank | 65 comment | 8 complexity | d00b2408827e47d888d51a6f9afa90f3 MD5 | raw file
  1// Copyright 2008 Christophe Henry
  2// henry UNDERSCORE christophe AT hotmail DOT com
  3// This is an extended version of the state machine available in the boost::mpl library
  4// Distributed under the same license as the original.
  5// Copyright for the original version:
  6// Copyright 2005 David Abrahams and Aleksey Gurtovoy. Distributed
  7// under the Boost Software License, Version 1.0. (See accompanying
  8// file LICENSE_1_0.txt or copy at
  9// http://www.boost.org/LICENSE_1_0.txt)
 10
 11#ifndef BOOST_MSM_BACK_METAFUNCTIONS_H
 12#define BOOST_MSM_BACK_METAFUNCTIONS_H
 13
 14#include <boost/mpl/set.hpp>
 15#include <boost/mpl/at.hpp>
 16#include <boost/mpl/pair.hpp>
 17#include <boost/mpl/map.hpp>
 18#include <boost/mpl/int.hpp>
 19#include <boost/mpl/has_xxx.hpp>
 20#include <boost/mpl/find.hpp>
 21#include <boost/mpl/count_if.hpp>
 22#include <boost/mpl/fold.hpp>
 23#include <boost/mpl/if.hpp>
 24#include <boost/mpl/has_key.hpp>
 25#include <boost/mpl/insert.hpp>
 26#include <boost/mpl/next_prior.hpp>
 27#include <boost/mpl/map.hpp>
 28#include <boost/mpl/push_back.hpp>
 29#include <boost/mpl/vector.hpp>
 30#include <boost/mpl/is_sequence.hpp>
 31#include <boost/mpl/size.hpp>
 32#include <boost/mpl/transform.hpp>
 33#include <boost/mpl/begin_end.hpp>
 34#include <boost/mpl/bool.hpp>
 35#include <boost/mpl/empty.hpp>
 36#include <boost/mpl/identity.hpp>
 37#include <boost/mpl/eval_if.hpp>
 38#include <boost/mpl/insert_range.hpp>
 39#include <boost/mpl/front.hpp>
 40#include <boost/mpl/logical.hpp>
 41#include <boost/mpl/plus.hpp>
 42#include <boost/mpl/copy_if.hpp>
 43#include <boost/mpl/back_inserter.hpp>
 44#include <boost/mpl/transform.hpp>
 45
 46#include <boost/type_traits/is_same.hpp>
 47#include <boost/utility/enable_if.hpp>
 48
 49// mpl_graph graph implementation and depth first search
 50#include <boost/msm/mpl_graph/incidence_list_graph.hpp>
 51#include <boost/msm/mpl_graph/depth_first_search.hpp>
 52
 53BOOST_MPL_HAS_XXX_TRAIT_DEF(explicit_creation)
 54BOOST_MPL_HAS_XXX_TRAIT_DEF(pseudo_entry)
 55BOOST_MPL_HAS_XXX_TRAIT_DEF(pseudo_exit)
 56BOOST_MPL_HAS_XXX_TRAIT_DEF(concrete_exit_state)
 57BOOST_MPL_HAS_XXX_TRAIT_DEF(composite_tag)
 58BOOST_MPL_HAS_XXX_TRAIT_DEF(not_real_row_tag)
 59BOOST_MPL_HAS_XXX_TRAIT_DEF(event_blocking_flag)
 60BOOST_MPL_HAS_XXX_TRAIT_DEF(explicit_entry_state)
 61BOOST_MPL_HAS_XXX_TRAIT_DEF(completion_event)
 62BOOST_MPL_HAS_XXX_TRAIT_DEF(no_exception_thrown)
 63BOOST_MPL_HAS_XXX_TRAIT_DEF(no_message_queue)
 64BOOST_MPL_HAS_XXX_TRAIT_DEF(activate_deferred_events)
 65BOOST_MPL_HAS_XXX_TRAIT_DEF(wrapped_entry)
 66BOOST_MPL_HAS_XXX_TRAIT_DEF(active_state_switch_policy)
 67
 68namespace boost { namespace msm { namespace back
 69{
 70template <typename Sequence, typename Range>
 71struct set_insert_range
 72{
 73    typedef typename ::boost::mpl::fold<
 74        Range,Sequence, 
 75        ::boost::mpl::insert< ::boost::mpl::placeholders::_1, ::boost::mpl::placeholders::_2 >
 76    >::type type;
 77};
 78
 79// returns the current state type of a transition
 80template <class Transition>
 81struct transition_source_type
 82{
 83    typedef typename Transition::current_state_type type;
 84};
 85
 86// returns the target state type of a transition
 87template <class Transition>
 88struct transition_target_type
 89{
 90    typedef typename Transition::next_state_type type;
 91};
 92
 93// helper functions for generate_state_ids
 94// create a pair of a state and a passed id for source and target states
 95template <class Id,class Transition>
 96struct make_pair_source_state_id
 97{
 98    typedef typename ::boost::mpl::pair<typename Transition::current_state_type,Id> type;
 99};
100template <class Id,class Transition>
101struct make_pair_target_state_id
102{
103    typedef typename ::boost::mpl::pair<typename Transition::next_state_type,Id> type;
104};
105
106// iterates through a transition table and automatically generates ids starting at 0
107// first the source states, transition up to down
108// then the target states, up to down
109template <class stt>
110struct generate_state_ids
111{
112    typedef typename 
113        ::boost::mpl::fold<
114        stt,::boost::mpl::pair< ::boost::mpl::map< >, ::boost::mpl::int_<0> >,
115        ::boost::mpl::pair<
116            ::boost::mpl::if_<
117                     ::boost::mpl::has_key< ::boost::mpl::first< ::boost::mpl::placeholders::_1>,
118                                            transition_source_type< ::boost::mpl::placeholders::_2> >,
119                     ::boost::mpl::first< ::boost::mpl::placeholders::_1>,
120                     ::boost::mpl::insert< ::boost::mpl::first<mpl::placeholders::_1>,
121                                make_pair_source_state_id< ::boost::mpl::second< ::boost::mpl::placeholders::_1 >,
122                                                           ::boost::mpl::placeholders::_2> >
123                      >,
124            ::boost::mpl::if_<
125                    ::boost::mpl::has_key< ::boost::mpl::first< ::boost::mpl::placeholders::_1>,
126                                           transition_source_type< ::boost::mpl::placeholders::_2> >,
127                    ::boost::mpl::second< ::boost::mpl::placeholders::_1 >,
128                    ::boost::mpl::next< ::boost::mpl::second<mpl::placeholders::_1 > >
129                    >
130        > //pair
131        >::type source_state_ids;
132    typedef typename ::boost::mpl::first<source_state_ids>::type source_state_map;
133    typedef typename ::boost::mpl::second<source_state_ids>::type highest_state_id;
134
135
136    typedef typename 
137        ::boost::mpl::fold<
138        stt,::boost::mpl::pair<source_state_map,highest_state_id >,
139        ::boost::mpl::pair<
140            ::boost::mpl::if_<
141                     ::boost::mpl::has_key< ::boost::mpl::first< ::boost::mpl::placeholders::_1>,
142                                            transition_target_type< ::boost::mpl::placeholders::_2> >,
143                     ::boost::mpl::first< ::boost::mpl::placeholders::_1>,
144                     ::boost::mpl::insert< ::boost::mpl::first< ::boost::mpl::placeholders::_1>,
145                                make_pair_target_state_id< ::boost::mpl::second< ::boost::mpl::placeholders::_1 >,
146                                ::boost::mpl::placeholders::_2> >
147                     >,
148            ::boost::mpl::if_<
149                    ::boost::mpl::has_key< ::boost::mpl::first< ::boost::mpl::placeholders::_1>,
150                                           transition_target_type< ::boost::mpl::placeholders::_2> >,
151                    ::boost::mpl::second< ::boost::mpl::placeholders::_1 >,
152                    ::boost::mpl::next< ::boost::mpl::second< ::boost::mpl::placeholders::_1 > >
153                    >
154        > //pair
155        >::type all_state_ids;
156    typedef typename ::boost::mpl::first<all_state_ids>::type type;
157};
158
159template <class Fsm>
160struct get_active_state_switch_policy_helper
161{
162    typedef typename Fsm::active_state_switch_policy type;
163};
164template <class Iter>
165struct get_active_state_switch_policy_helper2
166{
167    typedef typename boost::mpl::deref<Iter>::type Fsm;
168    typedef typename Fsm::active_state_switch_policy type;
169};
170// returns the active state switching policy
171template <class Fsm>
172struct get_active_state_switch_policy
173{
174    typedef typename ::boost::mpl::find_if<
175        typename Fsm::configuration,
176        has_active_state_switch_policy< ::boost::mpl::placeholders::_1 > >::type iter;
177
178    typedef typename ::boost::mpl::eval_if<
179        typename ::boost::is_same<
180            iter, 
181            typename ::boost::mpl::end<typename Fsm::configuration>::type
182        >::type,
183        get_active_state_switch_policy_helper<Fsm>,
184        get_active_state_switch_policy_helper2< iter >
185    >::type type;
186};
187
188// returns the id of a given state
189template <class stt,class State>
190struct get_state_id
191{
192    typedef typename ::boost::mpl::at<typename generate_state_ids<stt>::type,State>::type type;
193    enum {value = type::value};
194};
195
196// returns a mpl::vector containing the init states of a state machine
197template <class States>
198struct get_initial_states 
199{
200    typedef typename ::boost::mpl::if_<
201        ::boost::mpl::is_sequence<States>,
202        States,
203        typename ::boost::mpl::push_back< ::boost::mpl::vector0<>,States>::type >::type type;
204};
205
206// returns a mpl::int_ containing the size of a region. If the argument is not a sequence, returns 1
207template <class region>
208struct get_number_of_regions 
209{
210    typedef typename mpl::if_<
211        ::boost::mpl::is_sequence<region>,
212        ::boost::mpl::size<region>,
213        ::boost::mpl::int_<1> >::type type;
214};
215
216// builds a mpl::vector of initial states
217//TODO remove duplicate from get_initial_states
218template <class region>
219struct get_regions_as_sequence 
220{
221    typedef typename ::boost::mpl::if_<
222        ::boost::mpl::is_sequence<region>,
223        region,
224        typename ::boost::mpl::push_back< ::boost::mpl::vector0<>,region>::type >::type type;
225};
226
227template <class ToCreateSeq>
228struct get_explicit_creation_as_sequence 
229{
230    typedef typename ::boost::mpl::if_<
231        ::boost::mpl::is_sequence<ToCreateSeq>,
232        ToCreateSeq,
233        typename ::boost::mpl::push_back< ::boost::mpl::vector0<>,ToCreateSeq>::type >::type type;
234};
235
236// returns true if 2 transitions have the same source (used to remove duplicates in search of composite states)
237template <class stt,class Transition1,class Transition2>
238struct have_same_source
239{
240    enum {current_state1 = get_state_id<stt,typename Transition1::current_state_type >::type::value};
241    enum {current_state2 = get_state_id<stt,typename Transition2::current_state_type >::type::value};
242    enum {value = ((int)current_state1 == (int)current_state2) };
243};
244
245
246// A metafunction that returns the Event associated with a transition.
247template <class Transition>
248struct transition_event
249{
250    typedef typename Transition::transition_event type;
251};
252
253// returns true for composite states
254template <class State>
255struct is_composite_state
256{
257    enum {value = has_composite_tag<State>::type::value};
258    typedef typename has_composite_tag<State>::type type;
259};
260
261// transform a transition table in a container of source states
262template <class stt>
263struct keep_source_names
264{
265    // instead of the rows we want only the names of the states (from source)
266    typedef typename 
267        ::boost::mpl::transform<
268        stt,transition_source_type< ::boost::mpl::placeholders::_1> >::type type;
269};
270
271// transform a transition table in a container of target states
272template <class stt>
273struct keep_target_names
274{
275    // instead of the rows we want only the names of the states (from source)
276    typedef typename 
277        ::boost::mpl::transform<
278        stt,transition_target_type< ::boost::mpl::placeholders::_1> >::type type;
279};
280
281template <class stt>
282struct generate_state_set
283{
284    // keep in the original transition table only the source/target state types
285    typedef typename keep_source_names<stt>::type sources;
286    typedef typename keep_target_names<stt>::type targets;
287    typedef typename 
288        ::boost::mpl::fold<
289        sources, ::boost::mpl::set<>,
290        ::boost::mpl::insert< ::boost::mpl::placeholders::_1, ::boost::mpl::placeholders::_2>
291        >::type source_set;
292    typedef typename 
293        ::boost::mpl::fold<
294        targets,source_set,
295        ::boost::mpl::insert< ::boost::mpl::placeholders::_1, ::boost::mpl::placeholders::_2>
296        >::type type;
297};
298
299// iterates through the transition table and generate a mpl::set<> containing all the events
300template <class stt>
301struct generate_event_set
302{
303    typedef typename 
304        ::boost::mpl::fold<
305            stt, ::boost::mpl::set<>,
306            ::boost::mpl::if_<
307                ::boost::mpl::has_key< ::boost::mpl::placeholders::_1, 
308                                       transition_event< ::boost::mpl::placeholders::_2> >,
309                ::boost::mpl::placeholders::_1,
310                ::boost::mpl::insert< ::boost::mpl::placeholders::_1,
311                                      transition_event< ::boost::mpl::placeholders::_2> > >
312        >::type type;
313};
314
315// returns a mpl::bool_<true> if State has Event as deferred event
316template <class State, class Event>
317struct has_state_delayed_event  
318{
319    typedef typename ::boost::mpl::find<typename State::deferred_events,Event>::type found;
320    typedef typename ::boost::mpl::if_<
321        ::boost::is_same<found,typename ::boost::mpl::end<typename State::deferred_events>::type >,
322        ::boost::mpl::bool_<false>,
323        ::boost::mpl::bool_<true> >::type type;
324};
325// returns a mpl::bool_<true> if State has any deferred event
326template <class State>
327struct has_state_delayed_events  
328{
329    typedef typename ::boost::mpl::if_<
330        ::boost::mpl::empty<typename State::deferred_events>,
331        ::boost::mpl::bool_<false>,
332        ::boost::mpl::bool_<true> >::type type;
333};
334
335// Template used to create dummy entries for initial states not found in the stt.
336template< typename T1 >
337struct not_a_row
338{
339    typedef int not_real_row_tag;
340    struct dummy_event 
341    {
342    };
343    typedef T1                  current_state_type;
344    typedef T1                  next_state_type;
345    typedef dummy_event         transition_event;
346};
347
348// metafunctions used to find out if a state is entry, exit or something else
349template <class State>
350struct is_pseudo_entry 
351{
352    typedef typename ::boost::mpl::if_< typename has_pseudo_entry<State>::type,
353        ::boost::mpl::bool_<true>,::boost::mpl::bool_<false> 
354    >::type type;
355};
356// says if a state is an exit pseudo state
357template <class State>
358struct is_pseudo_exit 
359{
360    typedef typename ::boost::mpl::if_< typename has_pseudo_exit<State>::type,
361        ::boost::mpl::bool_<true>, ::boost::mpl::bool_<false> 
362    >::type type;
363};
364// says if a state is an entry pseudo state or an explicit entry
365template <class State>
366struct is_direct_entry 
367{
368    typedef typename ::boost::mpl::if_< typename has_explicit_entry_state<State>::type,
369        ::boost::mpl::bool_<true>, ::boost::mpl::bool_<false> 
370    >::type type;
371};
372
373//converts a "fake" (simulated in a state_machine_ description )state into one which will really get created
374template <class StateType,class CompositeType>
375struct convert_fake_state
376{
377    // converts a state (explicit entry) into the state we really are going to create (explicit<>)
378    typedef typename ::boost::mpl::if_<
379        typename is_direct_entry<StateType>::type,
380        typename CompositeType::template direct<StateType>,
381        typename ::boost::mpl::identity<StateType>::type
382    >::type type;
383};
384
385template <class StateType>
386struct get_explicit_creation 
387{
388    typedef typename StateType::explicit_creation type;
389};
390
391template <class StateType>
392struct get_wrapped_entry 
393{
394    typedef typename StateType::wrapped_entry type;
395};
396// used for states created with explicit_creation
397// if the state is an explicit entry, we reach for the wrapped state
398// otherwise, this returns the state itself
399template <class StateType>
400struct get_wrapped_state 
401{
402    typedef typename ::boost::mpl::eval_if<
403                typename has_wrapped_entry<StateType>::type,
404                get_wrapped_entry<StateType>,
405                ::boost::mpl::identity<StateType> >::type type;
406};
407
408template <class Derived>
409struct create_stt 
410{
411    //typedef typename Derived::transition_table stt;
412    typedef typename Derived::real_transition_table Stt;
413    // get the state set
414    typedef typename generate_state_set<Stt>::type states;
415    // transform the initial region(s) in a sequence
416    typedef typename get_regions_as_sequence<typename Derived::initial_state>::type init_states;
417    // iterate through the initial states and add them in the stt if not already there
418    typedef typename 
419        ::boost::mpl::fold<
420        init_states,Stt,
421        ::boost::mpl::if_<
422                 ::boost::mpl::has_key<states, ::boost::mpl::placeholders::_2>,
423                 ::boost::mpl::placeholders::_1,
424                 ::boost::mpl::insert< ::boost::mpl::placeholders::_1, ::boost::mpl::end< ::boost::mpl::placeholders::_1>,
425                             not_a_row< get_wrapped_state< ::boost::mpl::placeholders::_2> > > 
426                  >
427        >::type with_init;
428    // do the same for states marked as explicitly created
429    typedef typename get_explicit_creation_as_sequence<
430       typename ::boost::mpl::eval_if<
431            typename has_explicit_creation<Derived>::type,
432            get_explicit_creation<Derived>,
433            ::boost::mpl::vector0<> >::type
434        >::type fake_explicit_created;
435
436    typedef typename 
437        ::boost::mpl::transform<
438        fake_explicit_created,convert_fake_state< ::boost::mpl::placeholders::_1,Derived> >::type explicit_created;
439
440    typedef typename 
441        ::boost::mpl::fold<
442        explicit_created,with_init,
443        ::boost::mpl::if_<
444                 ::boost::mpl::has_key<states, ::boost::mpl::placeholders::_2>,
445                 ::boost::mpl::placeholders::_1,
446                 ::boost::mpl::insert< ::boost::mpl::placeholders::_1, ::boost::mpl::end<mpl::placeholders::_1>,
447                             not_a_row< get_wrapped_state< ::boost::mpl::placeholders::_2> > > 
448                  >
449        >::type type;
450};
451
452// returns the transition table of a Composite state
453template <class Composite>
454struct get_transition_table
455{
456    typedef typename create_stt<Composite>::type type;
457};
458// recursively get a transition table for a given composite state.
459// returns the transition table for this state + the tables of all composite sub states recursively
460template <class Composite>
461struct recursive_get_transition_table
462{
463    // get the transition table of the state if it's a state machine
464    typedef typename ::boost::mpl::eval_if<typename is_composite_state<Composite>::type,
465        get_transition_table<Composite>,
466        ::boost::mpl::vector0<> >::type org_table;
467
468    typedef typename generate_state_set<org_table>::type states;
469
470    // and for every substate, recursively get the transition table if it's a state machine
471    typedef typename ::boost::mpl::fold<
472        states,org_table,
473        ::boost::mpl::insert_range< ::boost::mpl::placeholders::_1, ::boost::mpl::end<mpl::placeholders::_1>,
474        recursive_get_transition_table< ::boost::mpl::placeholders::_2 > >
475    >::type type;
476
477};
478
479// metafunction used to say if a SM has pseudo exit states
480template <class Derived>
481struct has_fsm_deferred_events 
482{
483    typedef typename create_stt<Derived>::type Stt;
484    typedef typename generate_state_set<Stt>::type state_list;
485
486    typedef typename ::boost::mpl::or_<
487        typename has_activate_deferred_events<Derived>::type,
488        ::boost::mpl::bool_< ::boost::mpl::count_if<
489                typename Derived::configuration,
490                has_activate_deferred_events< ::boost::mpl::placeholders::_1 > >::value != 0> 
491    >::type found_in_fsm;
492
493    typedef typename ::boost::mpl::or_<
494            found_in_fsm,
495            ::boost::mpl::bool_< ::boost::mpl::count_if<
496                state_list,has_state_delayed_events<
497                    ::boost::mpl::placeholders::_1 > >::value != 0>
498            >::type type;
499};
500
501// returns a mpl::bool_<true> if State has any delayed event
502template <class Event>
503struct is_completion_event  
504{
505    typedef typename ::boost::mpl::if_<
506        has_completion_event<Event>,
507        ::boost::mpl::bool_<true>,
508        ::boost::mpl::bool_<false> >::type type;
509};
510// metafunction used to say if a SM has eventless transitions
511template <class Derived>
512struct has_fsm_eventless_transition 
513{
514    typedef typename create_stt<Derived>::type Stt;
515    typedef typename generate_event_set<Stt>::type event_list;
516
517    typedef ::boost::mpl::bool_< ::boost::mpl::count_if<
518        event_list,is_completion_event< ::boost::mpl::placeholders::_1 > >::value != 0> type;
519};
520template <class Derived>
521struct find_completion_events 
522{
523    typedef typename create_stt<Derived>::type Stt;
524    typedef typename generate_event_set<Stt>::type event_list;
525
526    typedef typename ::boost::mpl::fold<
527        event_list, ::boost::mpl::set<>,
528        ::boost::mpl::if_<
529                 is_completion_event< ::boost::mpl::placeholders::_2>,
530                 ::boost::mpl::insert< ::boost::mpl::placeholders::_1, ::boost::mpl::placeholders::_2 >, 
531                 ::boost::mpl::placeholders::_1 >
532    >::type type;
533};
534
535template <class Transition>
536struct make_vector 
537{
538    typedef ::boost::mpl::vector<Transition> type;
539};
540template< typename Entry > 
541struct get_first_element_pair_second
542{ 
543    typedef typename ::boost::mpl::front<typename Entry::second>::type type;
544}; 
545
546 //returns the owner of an explicit_entry state
547 //which is the containing SM if the transition originates from outside the containing SM
548 //or else the explicit_entry state itself
549template <class State,class ContainingSM>
550struct get_owner 
551{
552    typedef typename ::boost::mpl::if_<
553        typename ::boost::mpl::not_<typename ::boost::is_same<typename State::owner,
554                                                              ContainingSM >::type>::type,
555        typename State::owner, 
556        State >::type type;
557};
558
559template <class Sequence,class ContainingSM>
560struct get_fork_owner 
561{
562    typedef typename ::boost::mpl::front<Sequence>::type seq_front;
563    typedef typename ::boost::mpl::if_<
564                    typename ::boost::mpl::not_<
565                        typename ::boost::is_same<typename seq_front::owner,ContainingSM>::type>::type,
566                    typename seq_front::owner, 
567                    seq_front >::type type;
568};
569
570template <class StateType,class ContainingSM>
571struct make_exit 
572{
573    typedef typename ::boost::mpl::if_<
574             typename is_pseudo_exit<StateType>::type ,
575             typename ContainingSM::template exit_pt<StateType>,
576             typename ::boost::mpl::identity<StateType>::type
577            >::type type;
578};
579
580template <class StateType,class ContainingSM>
581struct make_entry 
582{
583    typedef typename ::boost::mpl::if_<
584        typename is_pseudo_entry<StateType>::type ,
585        typename ContainingSM::template entry_pt<StateType>,
586        typename ::boost::mpl::if_<
587                typename is_direct_entry<StateType>::type,
588                typename ContainingSM::template direct<StateType>,
589                typename ::boost::mpl::identity<StateType>::type
590                >::type
591        >::type type;
592};
593// metafunction used to say if a SM has pseudo exit states
594template <class StateType>
595struct has_exit_pseudo_states_helper 
596{
597    typedef typename StateType::stt Stt;
598    typedef typename generate_state_set<Stt>::type state_list;
599
600    typedef ::boost::mpl::bool_< ::boost::mpl::count_if<
601                state_list,is_pseudo_exit< ::boost::mpl::placeholders::_1> >::value != 0> type;
602};
603template <class StateType>
604struct has_exit_pseudo_states 
605{
606    typedef typename ::boost::mpl::eval_if<typename is_composite_state<StateType>::type,
607        has_exit_pseudo_states_helper<StateType>,
608        ::boost::mpl::bool_<false> >::type type;
609};
610
611template <class StateType>
612struct is_state_blocking 
613{
614    typedef typename ::boost::mpl::fold<
615        typename StateType::flag_list, ::boost::mpl::set<>,
616        ::boost::mpl::if_<
617                 has_event_blocking_flag< ::boost::mpl::placeholders::_2>,
618                 ::boost::mpl::insert< ::boost::mpl::placeholders::_1, ::boost::mpl::placeholders::_2 >, 
619                 ::boost::mpl::placeholders::_1 >
620    >::type blocking_flags;
621
622    typedef typename ::boost::mpl::if_<
623        ::boost::mpl::empty<blocking_flags>,
624        ::boost::mpl::bool_<false>,
625        ::boost::mpl::bool_<true> >::type type;
626};
627// returns a mpl::bool_<true> if fsm has an event blocking flag in one of its substates
628template <class StateType>
629struct has_fsm_blocking_states  
630{
631    typedef typename create_stt<StateType>::type Stt;
632    typedef typename generate_state_set<Stt>::type state_list;
633
634    typedef typename ::boost::mpl::fold<
635        state_list, ::boost::mpl::set<>,
636        ::boost::mpl::if_<
637                 is_state_blocking< ::boost::mpl::placeholders::_2>,
638                 ::boost::mpl::insert< ::boost::mpl::placeholders::_1, ::boost::mpl::placeholders::_2 >, 
639                 ::boost::mpl::placeholders::_1 >
640    >::type blocking_states;
641
642    typedef typename ::boost::mpl::if_<
643        ::boost::mpl::empty<blocking_states>,
644        ::boost::mpl::bool_<false>,
645        ::boost::mpl::bool_<true> >::type type;
646};
647
648template <class StateType>
649struct is_no_exception_thrown
650{
651    typedef ::boost::mpl::bool_< ::boost::mpl::count_if<
652        typename StateType::configuration,
653        has_no_exception_thrown< ::boost::mpl::placeholders::_1 > >::value != 0> found;
654
655    typedef typename ::boost::mpl::or_<
656        typename has_no_exception_thrown<StateType>::type,
657        found
658    >::type type;
659};
660
661template <class StateType>
662struct is_no_message_queue
663{
664    typedef ::boost::mpl::bool_< ::boost::mpl::count_if<
665        typename StateType::configuration,
666        has_no_message_queue< ::boost::mpl::placeholders::_1 > >::value != 0> found;
667
668    typedef typename ::boost::mpl::or_<
669        typename has_no_message_queue<StateType>::type,
670        found
671    >::type type;
672};
673
674template <class StateType>
675struct is_active_state_switch_policy 
676{
677    typedef ::boost::mpl::bool_< ::boost::mpl::count_if<
678        typename StateType::configuration,
679        has_active_state_switch_policy< ::boost::mpl::placeholders::_1 > >::value != 0> found;
680
681    typedef typename ::boost::mpl::or_<
682        typename has_active_state_switch_policy<StateType>::type,
683        found
684    >::type type;
685};
686
687template <class StateType>
688struct get_initial_event 
689{
690    typedef typename StateType::initial_event type;
691};
692
693template <class StateType>
694struct get_final_event 
695{
696    typedef typename StateType::final_event type;
697};
698
699template <class TransitionTable, class InitState>
700struct build_one_orthogonal_region 
701{
702     template<typename Row>
703     struct row_to_incidence :
704         ::boost::mpl::vector<
705                ::boost::mpl::pair<
706                    typename Row::next_state_type, 
707                    typename Row::transition_event>, 
708                typename Row::current_state_type, 
709                typename Row::next_state_type
710         > {};
711
712     template <class Seq, class Elt>
713     struct transition_incidence_list_helper 
714     {
715         typedef typename ::boost::mpl::push_back< Seq, row_to_incidence< Elt > >::type type;
716     };
717
718     typedef typename ::boost::mpl::fold<
719         TransitionTable,
720         ::boost::mpl::vector<>,
721         transition_incidence_list_helper< ::boost::mpl::placeholders::_1, ::boost::mpl::placeholders::_2>
722     >::type transition_incidence_list;
723
724     typedef ::boost::msm::mpl_graph::incidence_list_graph<transition_incidence_list>
725         transition_graph;
726
727     struct preordering_dfs_visitor : 
728         ::boost::msm::mpl_graph::dfs_default_visitor_operations 
729     {    
730         template<typename Node, typename Graph, typename State>
731         struct discover_vertex :
732             ::boost::mpl::insert<State, Node>
733         {};
734     };
735
736     typedef typename mpl::first< 
737         typename ::boost::msm::mpl_graph::depth_first_search<
738            transition_graph, 
739            preordering_dfs_visitor,
740            ::boost::mpl::set<>,
741            InitState
742         >::type
743     >::type type;
744};
745
746template <class Fsm>
747struct find_entry_states 
748{
749    typedef typename ::boost::mpl::copy<
750        typename Fsm::substate_list,
751        ::boost::mpl::inserter< 
752            ::boost::mpl::set0<>,
753            ::boost::mpl::if_<
754                has_explicit_entry_state< ::boost::mpl::placeholders::_2 >,
755                ::boost::mpl::insert< ::boost::mpl::placeholders::_1, ::boost::mpl::placeholders::_2>,
756                ::boost::mpl::placeholders::_1
757            >
758        >
759    >::type type;
760};
761
762template <class Set1, class Set2>
763struct is_common_element 
764{
765    typedef typename ::boost::mpl::fold<
766        Set1, ::boost::mpl::false_,
767        ::boost::mpl::if_<
768            ::boost::mpl::has_key<
769                Set2,
770                ::boost::mpl::placeholders::_2
771            >,
772            ::boost::mpl::true_,
773            ::boost::mpl::placeholders::_1
774        >
775    >::type type;
776};
777
778template <class EntryRegion, class AllRegions>
779struct add_entry_region 
780{
781    typedef typename ::boost::mpl::transform<
782        AllRegions, 
783        ::boost::mpl::if_<
784            is_common_element<EntryRegion, ::boost::mpl::placeholders::_1>,
785            set_insert_range< ::boost::mpl::placeholders::_1, EntryRegion>,
786            ::boost::mpl::placeholders::_1
787        >
788    >::type type;
789};
790
791// build a vector of regions states (as a set)
792// one set of states for every region
793template <class Fsm, class InitStates>
794struct build_orthogonal_regions 
795{
796    typedef typename 
797        ::boost::mpl::fold<
798            InitStates, ::boost::mpl::vector0<>,
799            ::boost::mpl::push_back< 
800                ::boost::mpl::placeholders::_1, 
801                build_one_orthogonal_region< typename Fsm::stt, ::boost::mpl::placeholders::_2 > >
802        >::type without_entries;
803
804    typedef typename 
805        ::boost::mpl::fold<
806        typename find_entry_states<Fsm>::type, ::boost::mpl::vector0<>,
807            ::boost::mpl::push_back< 
808                ::boost::mpl::placeholders::_1, 
809                build_one_orthogonal_region< typename Fsm::stt, ::boost::mpl::placeholders::_2 > >
810        >::type only_entries;
811
812    typedef typename ::boost::mpl::fold<
813        only_entries , without_entries,
814        add_entry_region< ::boost::mpl::placeholders::_2, ::boost::mpl::placeholders::_1>
815    >::type type;
816};
817
818template <class GraphAsSeqOfSets, class StateType>
819struct find_region_index
820{
821    typedef typename 
822        ::boost::mpl::fold<
823            GraphAsSeqOfSets, ::boost::mpl::pair< ::boost::mpl::int_< -1 > /*res*/, ::boost::mpl::int_<0> /*counter*/ >,
824            ::boost::mpl::if_<
825                ::boost::mpl::has_key< ::boost::mpl::placeholders::_2, StateType >,
826                ::boost::mpl::pair< 
827                    ::boost::mpl::second< ::boost::mpl::placeholders::_1 >,
828                    ::boost::mpl::next< ::boost::mpl::second< ::boost::mpl::placeholders::_1 > >
829                >,
830                ::boost::mpl::pair< 
831                    ::boost::mpl::first< ::boost::mpl::placeholders::_1 >,
832                    ::boost::mpl::next< ::boost::mpl::second< ::boost::mpl::placeholders::_1 > >
833                >
834            >
835        >::type result_pair;
836    typedef typename ::boost::mpl::first<result_pair>::type type;
837    enum {value = type::value};
838};
839
840template <class Fsm>
841struct check_regions_orthogonality
842{
843    typedef typename build_orthogonal_regions< Fsm,typename Fsm::initial_states>::type regions;
844    
845    typedef typename ::boost::mpl::fold<
846        regions, ::boost::mpl::int_<0>,
847        ::boost::mpl::plus< ::boost::mpl::placeholders::_1 , ::boost::mpl::size< ::boost::mpl::placeholders::_2> >
848    >::type number_of_states_in_regions;
849
850    typedef typename ::boost::mpl::fold<
851            regions,mpl::set0<>,
852            set_insert_range< 
853                    ::boost::mpl::placeholders::_1, 
854                    ::boost::mpl::placeholders::_2 > 
855    >::type one_big_states_set;
856
857    enum {states_in_regions_raw = number_of_states_in_regions::value};
858    enum {cumulated_states_in_regions_raw = ::boost::mpl::size<one_big_states_set>::value};
859};
860
861template <class Fsm>
862struct check_no_unreachable_state
863{
864    typedef typename check_regions_orthogonality<Fsm>::one_big_states_set states_in_regions;
865
866    typedef typename set_insert_range<
867        states_in_regions, 
868        typename ::boost::mpl::eval_if<
869            typename has_explicit_creation<Fsm>::type,
870            get_explicit_creation<Fsm>,
871            ::boost::mpl::vector0<>
872        >::type
873    >::type with_explicit_creation;
874
875    enum {states_in_fsm = ::boost::mpl::size< typename Fsm::substate_list >::value};
876    enum {cumulated_states_in_regions = ::boost::mpl::size< with_explicit_creation >::value};
877};
878
879// helper to find out if a SM has an active exit state and is therefore waiting for exiting
880template <class StateType,class OwnerFct,class FSM>
881inline
882typename ::boost::enable_if<typename ::boost::mpl::and_<typename is_composite_state<FSM>::type,
883                                                        typename is_pseudo_exit<StateType>::type>,bool >::type
884is_exit_state_active(FSM& fsm)
885{
886    typedef typename OwnerFct::type Composite;
887    //typedef typename create_stt<Composite>::type stt;
888    typedef typename Composite::stt stt;
889    int state_id = get_state_id<stt,StateType>::type::value;
890    Composite& comp = fsm.template get_state<Composite&>();
891    return (std::find(comp.current_state(),comp.current_state()+Composite::nr_regions::value,state_id)
892                            !=comp.current_state()+Composite::nr_regions::value);
893}
894template <class StateType,class OwnerFct,class FSM>
895inline
896typename ::boost::disable_if<typename ::boost::mpl::and_<typename is_composite_state<FSM>::type,
897                                                         typename is_pseudo_exit<StateType>::type>,bool >::type
898is_exit_state_active(FSM&)
899{
900    return false;
901}
902
903} } }//boost::msm::back
904
905#endif // BOOST_MSM_BACK_METAFUNCTIONS_H
906