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