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