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_FRONT_FUNCTOR_ROW_H
|
Chris@16
|
12 #define BOOST_MSM_FRONT_FUNCTOR_ROW_H
|
Chris@16
|
13
|
Chris@16
|
14 #include <boost/mpl/set.hpp>
|
Chris@16
|
15 #include <boost/mpl/for_each.hpp>
|
Chris@16
|
16 #include <boost/mpl/has_xxx.hpp>
|
Chris@16
|
17 #include <boost/mpl/count_if.hpp>
|
Chris@16
|
18
|
Chris@16
|
19 #include <boost/typeof/typeof.hpp>
|
Chris@16
|
20
|
Chris@16
|
21 #include <boost/msm/back/common_types.hpp>
|
Chris@16
|
22 #include <boost/msm/row_tags.hpp>
|
Chris@16
|
23 #include <boost/msm/common.hpp>
|
Chris@16
|
24 #include <boost/msm/front/completion_event.hpp>
|
Chris@16
|
25
|
Chris@16
|
26 #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
|
Chris@16
|
27
|
Chris@16
|
28 BOOST_MPL_HAS_XXX_TRAIT_DEF(deferring_action)
|
Chris@16
|
29 BOOST_MPL_HAS_XXX_TRAIT_DEF(some_deferring_actions)
|
Chris@16
|
30
|
Chris@16
|
31 namespace boost { namespace msm { namespace front
|
Chris@16
|
32 {
|
Chris@16
|
33 template <class Func,class Enable=void>
|
Chris@16
|
34 struct get_functor_return_value
|
Chris@16
|
35 {
|
Chris@16
|
36 static const ::boost::msm::back::HandledEnum value = ::boost::msm::back::HANDLED_TRUE;
|
Chris@16
|
37 };
|
Chris@16
|
38 template <class Func>
|
Chris@16
|
39 struct get_functor_return_value<Func,
|
Chris@16
|
40 typename ::boost::enable_if<
|
Chris@16
|
41 typename has_deferring_action<Func>::type
|
Chris@16
|
42 >::type
|
Chris@16
|
43 >
|
Chris@16
|
44 {
|
Chris@16
|
45 static const ::boost::msm::back::HandledEnum value = ::boost::msm::back::HANDLED_DEFERRED;
|
Chris@16
|
46 };
|
Chris@16
|
47 // for sequences
|
Chris@16
|
48 template <class Func>
|
Chris@16
|
49 struct get_functor_return_value<Func,
|
Chris@16
|
50 typename ::boost::enable_if<
|
Chris@16
|
51 typename has_some_deferring_actions<Func>::type
|
Chris@16
|
52 >::type
|
Chris@16
|
53 >
|
Chris@16
|
54 {
|
Chris@16
|
55 static const ::boost::msm::back::HandledEnum value =
|
Chris@16
|
56 (Func::some_deferring_actions::value ? ::boost::msm::back::HANDLED_DEFERRED : ::boost::msm::back::HANDLED_TRUE );
|
Chris@16
|
57 };
|
Chris@16
|
58 template <class SOURCE,class EVENT,class TARGET,class ACTION=none,class GUARD=none>
|
Chris@16
|
59 struct Row
|
Chris@16
|
60 {
|
Chris@16
|
61 typedef SOURCE Source;
|
Chris@16
|
62 typedef EVENT Evt;
|
Chris@16
|
63 typedef TARGET Target;
|
Chris@16
|
64 typedef ACTION Action;
|
Chris@16
|
65 typedef GUARD Guard;
|
Chris@16
|
66 // action plus guard
|
Chris@16
|
67 typedef row_tag row_type_tag;
|
Chris@16
|
68 template <class EVT,class FSM,class SourceState,class TargetState,class AllStates>
|
Chris@16
|
69 static ::boost::msm::back::HandledEnum action_call(FSM& fsm,EVT const& evt,SourceState& src,TargetState& tgt, AllStates&)
|
Chris@16
|
70 {
|
Chris@16
|
71 // create functor, call it
|
Chris@16
|
72 Action()(evt,fsm,src,tgt);
|
Chris@16
|
73 return get_functor_return_value<Action>::value;
|
Chris@16
|
74 }
|
Chris@16
|
75 template <class EVT,class FSM,class SourceState,class TargetState,class AllStates>
|
Chris@16
|
76 static bool guard_call(FSM& fsm,EVT const& evt,SourceState& src,TargetState& tgt,AllStates&)
|
Chris@16
|
77 {
|
Chris@16
|
78 // create functor, call it
|
Chris@16
|
79 return Guard()(evt,fsm,src,tgt);
|
Chris@16
|
80 }
|
Chris@16
|
81 };
|
Chris@16
|
82
|
Chris@16
|
83 template<class SOURCE,class EVENT,class TARGET>
|
Chris@16
|
84 struct Row<SOURCE,EVENT,TARGET,none,none>
|
Chris@16
|
85 {
|
Chris@16
|
86 typedef SOURCE Source;
|
Chris@16
|
87 typedef EVENT Evt;
|
Chris@16
|
88 typedef TARGET Target;
|
Chris@16
|
89 typedef none Action;
|
Chris@16
|
90 typedef none Guard;
|
Chris@16
|
91 // no action, no guard
|
Chris@16
|
92 typedef _row_tag row_type_tag;
|
Chris@16
|
93 };
|
Chris@16
|
94 template<class SOURCE,class EVENT,class TARGET,class ACTION>
|
Chris@16
|
95 struct Row<SOURCE,EVENT,TARGET,ACTION,none>
|
Chris@16
|
96 {
|
Chris@16
|
97 typedef SOURCE Source;
|
Chris@16
|
98 typedef EVENT Evt;
|
Chris@16
|
99 typedef TARGET Target;
|
Chris@16
|
100 typedef ACTION Action;
|
Chris@16
|
101 typedef none Guard;
|
Chris@16
|
102 // no guard
|
Chris@16
|
103 typedef a_row_tag row_type_tag;
|
Chris@16
|
104 template <class EVT,class FSM,class SourceState,class TargetState,class AllStates>
|
Chris@16
|
105 static ::boost::msm::back::HandledEnum action_call(FSM& fsm,EVT const& evt,SourceState& src,TargetState& tgt, AllStates&)
|
Chris@16
|
106 {
|
Chris@16
|
107 // create functor, call it
|
Chris@16
|
108 Action()(evt,fsm,src,tgt);
|
Chris@16
|
109 return get_functor_return_value<Action>::value;
|
Chris@16
|
110 }
|
Chris@16
|
111 };
|
Chris@16
|
112 template<class SOURCE,class EVENT,class TARGET,class GUARD>
|
Chris@16
|
113 struct Row<SOURCE,EVENT,TARGET,none,GUARD>
|
Chris@16
|
114 {
|
Chris@16
|
115 typedef SOURCE Source;
|
Chris@16
|
116 typedef EVENT Evt;
|
Chris@16
|
117 typedef TARGET Target;
|
Chris@16
|
118 typedef none Action;
|
Chris@16
|
119 typedef GUARD Guard;
|
Chris@16
|
120 // no action
|
Chris@16
|
121 typedef g_row_tag row_type_tag;
|
Chris@16
|
122 template <class EVT,class FSM,class SourceState,class TargetState,class AllStates>
|
Chris@16
|
123 static bool guard_call(FSM& fsm,EVT const& evt,SourceState& src,TargetState& tgt, AllStates&)
|
Chris@16
|
124 {
|
Chris@16
|
125 // create functor, call it
|
Chris@16
|
126 return Guard()(evt,fsm,src,tgt);
|
Chris@16
|
127 }
|
Chris@16
|
128 };
|
Chris@16
|
129 // internal transitions
|
Chris@16
|
130 template<class SOURCE,class EVENT,class ACTION>
|
Chris@16
|
131 struct Row<SOURCE,EVENT,none,ACTION,none>
|
Chris@16
|
132 {
|
Chris@16
|
133 typedef SOURCE Source;
|
Chris@16
|
134 typedef EVENT Evt;
|
Chris@16
|
135 typedef Source Target;
|
Chris@16
|
136 typedef ACTION Action;
|
Chris@16
|
137 typedef none Guard;
|
Chris@16
|
138 // no guard
|
Chris@16
|
139 typedef a_irow_tag row_type_tag;
|
Chris@16
|
140 template <class EVT,class FSM,class SourceState,class TargetState,class AllStates>
|
Chris@16
|
141 static ::boost::msm::back::HandledEnum action_call(FSM& fsm,EVT const& evt,SourceState& src,TargetState& tgt, AllStates&)
|
Chris@16
|
142 {
|
Chris@16
|
143 // create functor, call it
|
Chris@16
|
144 Action()(evt,fsm,src,tgt);
|
Chris@16
|
145 return get_functor_return_value<Action>::value;
|
Chris@16
|
146 }
|
Chris@16
|
147 };
|
Chris@16
|
148 template<class SOURCE,class EVENT,class GUARD>
|
Chris@16
|
149 struct Row<SOURCE,EVENT,none,none,GUARD>
|
Chris@16
|
150 {
|
Chris@16
|
151 typedef SOURCE Source;
|
Chris@16
|
152 typedef EVENT Evt;
|
Chris@16
|
153 typedef Source Target;
|
Chris@16
|
154 typedef none Action;
|
Chris@16
|
155 typedef GUARD Guard;
|
Chris@16
|
156 // no action
|
Chris@16
|
157 typedef g_irow_tag row_type_tag;
|
Chris@16
|
158 template <class EVT,class FSM,class SourceState,class TargetState,class AllStates>
|
Chris@16
|
159 static bool guard_call(FSM& fsm,EVT const& evt,SourceState& src,TargetState& tgt, AllStates&)
|
Chris@16
|
160 {
|
Chris@16
|
161 // create functor, call it
|
Chris@16
|
162 return Guard()(evt,fsm,src,tgt);
|
Chris@16
|
163 }
|
Chris@16
|
164 };
|
Chris@16
|
165 template<class SOURCE,class EVENT,class ACTION,class GUARD>
|
Chris@16
|
166 struct Row<SOURCE,EVENT,none,ACTION,GUARD>
|
Chris@16
|
167 {
|
Chris@16
|
168 typedef SOURCE Source;
|
Chris@16
|
169 typedef EVENT Evt;
|
Chris@16
|
170 typedef Source Target;
|
Chris@16
|
171 typedef ACTION Action;
|
Chris@16
|
172 typedef GUARD Guard;
|
Chris@16
|
173 // action + guard
|
Chris@16
|
174 typedef irow_tag row_type_tag;
|
Chris@16
|
175 template <class EVT,class FSM,class SourceState,class TargetState,class AllStates>
|
Chris@16
|
176 static ::boost::msm::back::HandledEnum action_call(FSM& fsm,EVT const& evt,SourceState& src,TargetState& tgt, AllStates&)
|
Chris@16
|
177 {
|
Chris@16
|
178 // create functor, call it
|
Chris@16
|
179 Action()(evt,fsm,src,tgt);
|
Chris@16
|
180 return get_functor_return_value<Action>::value;
|
Chris@16
|
181 }
|
Chris@16
|
182 template <class EVT,class FSM,class SourceState,class TargetState,class AllStates>
|
Chris@16
|
183 static bool guard_call(FSM& fsm,EVT const& evt,SourceState& src,TargetState& tgt, AllStates&)
|
Chris@16
|
184 {
|
Chris@16
|
185 // create functor, call it
|
Chris@16
|
186 return Guard()(evt,fsm,src,tgt);
|
Chris@16
|
187 }
|
Chris@16
|
188 };
|
Chris@16
|
189 template<class SOURCE,class EVENT>
|
Chris@16
|
190 struct Row<SOURCE,EVENT,none,none,none>
|
Chris@16
|
191 {
|
Chris@16
|
192 typedef SOURCE Source;
|
Chris@16
|
193 typedef EVENT Evt;
|
Chris@16
|
194 typedef Source Target;
|
Chris@16
|
195 typedef none Action;
|
Chris@16
|
196 typedef none Guard;
|
Chris@16
|
197 // no action, no guard
|
Chris@16
|
198 typedef _irow_tag row_type_tag;
|
Chris@16
|
199 };
|
Chris@16
|
200 template<class TGT>
|
Chris@16
|
201 struct get_row_target
|
Chris@16
|
202 {
|
Chris@16
|
203 typedef typename TGT::Target type;
|
Chris@16
|
204 };
|
Chris@16
|
205
|
Chris@16
|
206 template <class EVENT,class ACTION=none,class GUARD=none>
|
Chris@16
|
207 struct Internal
|
Chris@16
|
208 {
|
Chris@16
|
209 typedef EVENT Evt;
|
Chris@16
|
210 typedef ACTION Action;
|
Chris@16
|
211 typedef GUARD Guard;
|
Chris@16
|
212 // action plus guard
|
Chris@16
|
213 typedef sm_i_row_tag row_type_tag;
|
Chris@16
|
214 template <class EVT,class FSM,class SourceState,class TargetState,class AllStates>
|
Chris@16
|
215 static ::boost::msm::back::HandledEnum action_call(FSM& fsm,EVT const& evt,SourceState& src,TargetState& tgt, AllStates&)
|
Chris@16
|
216 {
|
Chris@16
|
217 // create functor, call it
|
Chris@16
|
218 Action()(evt,fsm,src,tgt);
|
Chris@16
|
219 return get_functor_return_value<Action>::value;
|
Chris@16
|
220 }
|
Chris@16
|
221 template <class EVT,class FSM,class SourceState,class TargetState,class AllStates>
|
Chris@16
|
222 static bool guard_call(FSM& fsm,EVT const& evt,SourceState& src,TargetState& tgt, AllStates&)
|
Chris@16
|
223 {
|
Chris@16
|
224 // create functor, call it
|
Chris@16
|
225 return Guard()(evt,fsm,src,tgt);
|
Chris@16
|
226 }
|
Chris@16
|
227 };
|
Chris@16
|
228
|
Chris@16
|
229 template<class EVENT,class ACTION>
|
Chris@16
|
230 struct Internal<EVENT,ACTION,none>
|
Chris@16
|
231 {
|
Chris@16
|
232 typedef EVENT Evt;
|
Chris@16
|
233 typedef ACTION Action;
|
Chris@16
|
234 typedef none Guard;
|
Chris@16
|
235 // no guard
|
Chris@16
|
236 typedef sm_a_i_row_tag row_type_tag;
|
Chris@16
|
237 template <class EVT,class FSM,class SourceState,class TargetState,class AllStates>
|
Chris@16
|
238 static ::boost::msm::back::HandledEnum action_call(FSM& fsm,EVT const& evt,SourceState& src,TargetState& tgt, AllStates&)
|
Chris@16
|
239 {
|
Chris@16
|
240 // create functor, call it
|
Chris@16
|
241 Action()(evt,fsm,src,tgt);
|
Chris@16
|
242 return get_functor_return_value<Action>::value;
|
Chris@16
|
243 }
|
Chris@16
|
244 };
|
Chris@16
|
245 template<class EVENT,class GUARD>
|
Chris@16
|
246 struct Internal<EVENT,none,GUARD>
|
Chris@16
|
247 {
|
Chris@16
|
248 typedef EVENT Evt;
|
Chris@16
|
249 typedef none Action;
|
Chris@16
|
250 typedef GUARD Guard;
|
Chris@16
|
251 // no action
|
Chris@16
|
252 typedef sm_g_i_row_tag row_type_tag;
|
Chris@16
|
253 template <class EVT,class FSM,class SourceState,class TargetState,class AllStates>
|
Chris@16
|
254 static bool guard_call(FSM& fsm,EVT const& evt,SourceState& src,TargetState& tgt, AllStates&)
|
Chris@16
|
255 {
|
Chris@16
|
256 // create functor, call it
|
Chris@16
|
257 return Guard()(evt,fsm,src,tgt);
|
Chris@16
|
258 }
|
Chris@16
|
259 };
|
Chris@16
|
260 template<class EVENT>
|
Chris@16
|
261 struct Internal<EVENT,none,none>
|
Chris@16
|
262 {
|
Chris@16
|
263 typedef EVENT Evt;
|
Chris@16
|
264 typedef none Action;
|
Chris@16
|
265 typedef none Guard;
|
Chris@16
|
266 // no action, no guard
|
Chris@16
|
267 typedef sm__i_row_tag row_type_tag;
|
Chris@16
|
268 };
|
Chris@16
|
269 struct event_tag{};
|
Chris@16
|
270 struct action_tag{};
|
Chris@16
|
271 struct state_action_tag{};
|
Chris@16
|
272 struct flag_tag{};
|
Chris@16
|
273 struct config_tag{};
|
Chris@16
|
274 struct not_euml_tag{};
|
Chris@16
|
275
|
Chris@16
|
276 template <class Sequence>
|
Chris@16
|
277 struct ActionSequence_
|
Chris@16
|
278 {
|
Chris@16
|
279 typedef Sequence sequence;
|
Chris@16
|
280 // if one functor of the sequence defers events, the complete sequence does
|
Chris@16
|
281 typedef ::boost::mpl::bool_<
|
Chris@16
|
282 ::boost::mpl::count_if<sequence,
|
Chris@16
|
283 has_deferring_action< ::boost::mpl::placeholders::_1 >
|
Chris@16
|
284 >::value != 0> some_deferring_actions;
|
Chris@16
|
285
|
Chris@16
|
286 template <class Event,class FSM,class STATE >
|
Chris@16
|
287 struct state_action_result
|
Chris@16
|
288 {
|
Chris@16
|
289 typedef void type;
|
Chris@16
|
290 };
|
Chris@16
|
291 template <class EVT,class FSM,class STATE>
|
Chris@16
|
292 struct Call
|
Chris@16
|
293 {
|
Chris@16
|
294 Call(EVT const& evt,FSM& fsm,STATE& state):
|
Chris@16
|
295 evt_(evt),fsm_(fsm),state_(state){}
|
Chris@16
|
296 template <class FCT>
|
Chris@16
|
297 void operator()(::boost::msm::wrap<FCT> const& )
|
Chris@16
|
298 {
|
Chris@16
|
299 FCT()(evt_,fsm_,state_);
|
Chris@16
|
300 }
|
Chris@16
|
301 private:
|
Chris@16
|
302 EVT const& evt_;
|
Chris@16
|
303 FSM& fsm_;
|
Chris@16
|
304 STATE& state_;
|
Chris@16
|
305 };
|
Chris@16
|
306 template <class EVT,class FSM,class SourceState,class TargetState>
|
Chris@16
|
307 struct transition_action_result
|
Chris@16
|
308 {
|
Chris@16
|
309 typedef void type;
|
Chris@16
|
310 };
|
Chris@16
|
311 template <class EVT,class FSM,class SourceState,class TargetState>
|
Chris@16
|
312 struct Call2
|
Chris@16
|
313 {
|
Chris@16
|
314 Call2(EVT const& evt,FSM& fsm,SourceState& src,TargetState& tgt):
|
Chris@16
|
315 evt_(evt),fsm_(fsm),src_(src),tgt_(tgt){}
|
Chris@16
|
316 template <class FCT>
|
Chris@16
|
317 void operator()(::boost::msm::wrap<FCT> const& )
|
Chris@16
|
318 {
|
Chris@16
|
319 FCT()(evt_,fsm_,src_,tgt_);
|
Chris@16
|
320 }
|
Chris@16
|
321 private:
|
Chris@16
|
322 EVT const & evt_;
|
Chris@16
|
323 FSM& fsm_;
|
Chris@16
|
324 SourceState& src_;
|
Chris@16
|
325 TargetState& tgt_;
|
Chris@16
|
326 };
|
Chris@16
|
327
|
Chris@16
|
328 typedef ::boost::mpl::set<state_action_tag,action_tag> tag_type;
|
Chris@16
|
329
|
Chris@16
|
330 template <class EVT,class FSM,class STATE>
|
Chris@16
|
331 void operator()(EVT const& evt,FSM& fsm,STATE& state)
|
Chris@16
|
332 {
|
Chris@16
|
333 mpl::for_each<Sequence,boost::msm::wrap< ::boost::mpl::placeholders::_1> >
|
Chris@16
|
334 (Call<EVT,FSM,STATE>(evt,fsm,state));
|
Chris@16
|
335 }
|
Chris@16
|
336 template <class EVT,class FSM,class SourceState,class TargetState>
|
Chris@16
|
337 void operator()(EVT const& evt,FSM& fsm,SourceState& src,TargetState& tgt)
|
Chris@16
|
338 {
|
Chris@16
|
339 mpl::for_each<Sequence,boost::msm::wrap< ::boost::mpl::placeholders::_1> >
|
Chris@16
|
340 (Call2<EVT,FSM,SourceState,TargetState>(evt,fsm,src,tgt));
|
Chris@16
|
341 }
|
Chris@16
|
342 };
|
Chris@16
|
343
|
Chris@16
|
344 // functor pre-defined for basic functionality
|
Chris@16
|
345 struct Defer
|
Chris@16
|
346 {
|
Chris@16
|
347 // mark as deferring to avoid stack overflows in certain conditions
|
Chris@16
|
348 typedef int deferring_action;
|
Chris@16
|
349 template <class EVT,class FSM,class SourceState,class TargetState>
|
Chris@16
|
350 void operator()(EVT const& evt,FSM& fsm,SourceState& ,TargetState& ) const
|
Chris@16
|
351 {
|
Chris@16
|
352 fsm.defer_event(evt);
|
Chris@16
|
353 }
|
Chris@16
|
354 };
|
Chris@16
|
355 }}}
|
Chris@16
|
356 #endif //BOOST_MSM_FRONT_FUNCTOR_ROW_H
|