Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/generic/include/boost/msm/back/metafunctions.hpp @ 16:2665513ce2d3
Add boost headers
author | Chris Cannam |
---|---|
date | Tue, 05 Aug 2014 11:11:38 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
15:663ca0da4350 | 16:2665513ce2d3 |
---|---|
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 | |
55 BOOST_MPL_HAS_XXX_TRAIT_DEF(explicit_creation) | |
56 BOOST_MPL_HAS_XXX_TRAIT_DEF(pseudo_entry) | |
57 BOOST_MPL_HAS_XXX_TRAIT_DEF(pseudo_exit) | |
58 BOOST_MPL_HAS_XXX_TRAIT_DEF(concrete_exit_state) | |
59 BOOST_MPL_HAS_XXX_TRAIT_DEF(composite_tag) | |
60 BOOST_MPL_HAS_XXX_TRAIT_DEF(not_real_row_tag) | |
61 BOOST_MPL_HAS_XXX_TRAIT_DEF(event_blocking_flag) | |
62 BOOST_MPL_HAS_XXX_TRAIT_DEF(explicit_entry_state) | |
63 BOOST_MPL_HAS_XXX_TRAIT_DEF(completion_event) | |
64 BOOST_MPL_HAS_XXX_TRAIT_DEF(no_exception_thrown) | |
65 BOOST_MPL_HAS_XXX_TRAIT_DEF(no_message_queue) | |
66 BOOST_MPL_HAS_XXX_TRAIT_DEF(activate_deferred_events) | |
67 BOOST_MPL_HAS_XXX_TRAIT_DEF(wrapped_entry) | |
68 BOOST_MPL_HAS_XXX_TRAIT_DEF(active_state_switch_policy) | |
69 | |
70 namespace boost { namespace msm { namespace back | |
71 { | |
72 template <typename Sequence, typename Range> | |
73 struct 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 | |
82 template <class Transition> | |
83 struct transition_source_type | |
84 { | |
85 typedef typename Transition::current_state_type type; | |
86 }; | |
87 | |
88 // returns the target state type of a transition | |
89 template <class Transition> | |
90 struct 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 | |
97 template <class Id,class Transition> | |
98 struct make_pair_source_state_id | |
99 { | |
100 typedef typename ::boost::mpl::pair<typename Transition::current_state_type,Id> type; | |
101 }; | |
102 template <class Id,class Transition> | |
103 struct 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 | |
111 template <class stt> | |
112 struct 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 | |
161 template <class Fsm> | |
162 struct get_active_state_switch_policy_helper | |
163 { | |
164 typedef typename Fsm::active_state_switch_policy type; | |
165 }; | |
166 template <class Iter> | |
167 struct 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 | |
173 template <class Fsm> | |
174 struct 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 | |
191 template <class stt,class State> | |
192 struct 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 | |
199 template <class States> | |
200 struct 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 | |
208 template <class region> | |
209 struct 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 | |
219 template <class region> | |
220 struct 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 | |
228 template <class ToCreateSeq> | |
229 struct 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) | |
238 template <class stt,class Transition1,class Transition2> | |
239 struct 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. | |
248 template <class Transition> | |
249 struct transition_event | |
250 { | |
251 typedef typename Transition::transition_event type; | |
252 }; | |
253 | |
254 // returns true for composite states | |
255 template <class State> | |
256 struct 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 | |
263 template <class stt> | |
264 struct 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 | |
273 template <class stt> | |
274 struct 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 | |
282 template <class stt> | |
283 struct 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 | |
301 template <class stt> | |
302 struct 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 | |
317 template <class State, class Event> | |
318 struct 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 | |
327 template <class State> | |
328 struct 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. | |
337 template< typename T1 > | |
338 struct 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 | |
350 template <class State> | |
351 struct 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 | |
358 template <class State> | |
359 struct 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 | |
366 template <class State> | |
367 struct 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 | |
375 template <class StateType,class CompositeType> | |
376 struct 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 | |
386 template <class StateType> | |
387 struct get_explicit_creation | |
388 { | |
389 typedef typename StateType::explicit_creation type; | |
390 }; | |
391 | |
392 template <class StateType> | |
393 struct 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 | |
400 template <class StateType> | |
401 struct 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 | |
409 template <class Derived> | |
410 struct 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 | |
454 template <class Composite> | |
455 struct 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 | |
462 template <class StateType,class IsComposite> | |
463 struct 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) | |
477 template <class StateType> | |
478 struct 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 | |
484 template <class Composite> | |
485 struct 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 | |
505 template <class Derived> | |
506 struct 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 | |
527 template <class Event> | |
528 struct 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 | |
536 template <class Derived> | |
537 struct 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 }; | |
545 template <class Derived> | |
546 struct 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 | |
560 template <class Transition> | |
561 struct make_vector | |
562 { | |
563 typedef ::boost::mpl::vector<Transition> type; | |
564 }; | |
565 template< typename Entry > | |
566 struct 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 | |
574 template <class State,class ContainingSM> | |
575 struct 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 | |
584 template <class Sequence,class ContainingSM> | |
585 struct 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 | |
595 template <class StateType,class ContainingSM> | |
596 struct 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 | |
605 template <class StateType,class ContainingSM> | |
606 struct 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 | |
619 template <class StateType> | |
620 struct 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 }; | |
628 template <class StateType> | |
629 struct 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 | |
637 template <class StateType> | |
638 struct 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 | |
647 template <class StateType> | |
648 struct 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 | |
664 template <class StateType> | |
665 struct 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 | |
684 template <class StateType> | |
685 struct 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 | |
697 template <class StateType> | |
698 struct 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 | |
710 template <class StateType> | |
711 struct 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 | |
723 template <class StateType> | |
724 struct get_initial_event | |
725 { | |
726 typedef typename StateType::initial_event type; | |
727 }; | |
728 | |
729 template <class StateType> | |
730 struct get_final_event | |
731 { | |
732 typedef typename StateType::final_event type; | |
733 }; | |
734 | |
735 template <class TransitionTable, class InitState> | |
736 struct 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 | |
782 template <class Fsm> | |
783 struct 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 | |
798 template <class Set1, class Set2> | |
799 struct 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 | |
814 template <class EntryRegion, class AllRegions> | |
815 struct 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 | |
829 template <class Fsm, class InitStates> | |
830 struct 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 | |
854 template <class GraphAsSeqOfSets, class StateType> | |
855 struct 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 | |
876 template <class Fsm> | |
877 struct 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 | |
897 template <class Fsm> | |
898 struct 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 | |
916 template <class StateType,class OwnerFct,class FSM> | |
917 inline | |
918 typename ::boost::enable_if<typename ::boost::mpl::and_<typename is_composite_state<FSM>::type, | |
919 typename is_pseudo_exit<StateType>::type>,bool >::type | |
920 is_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 } | |
930 template <class StateType,class OwnerFct,class FSM> | |
931 inline | |
932 typename ::boost::disable_if<typename ::boost::mpl::and_<typename is_composite_state<FSM>::type, | |
933 typename is_pseudo_exit<StateType>::type>,bool >::type | |
934 is_exit_state_active(FSM&) | |
935 { | |
936 return false; | |
937 } | |
938 | |
939 // transformation metafunction to end interrupt flags | |
940 template <class Event> | |
941 struct 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> | |
946 template <class Events> | |
947 struct 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 | |
954 template <class Event> | |
955 struct 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 | |
963 template <class Events> | |
964 struct 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 |