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)
11 #ifndef BOOST_MSM_FRONT_FUNCTOR_ROW_H
12 #define BOOST_MSM_FRONT_FUNCTOR_ROW_H
14 #include <boost/mpl/set.hpp>
15 #include <boost/mpl/for_each.hpp>
16 #include <boost/mpl/has_xxx.hpp>
17 #include <boost/mpl/count_if.hpp>
19 #include <boost/typeof/typeof.hpp>
21 #include <boost/msm/back/common_types.hpp>
22 #include <boost/msm/row_tags.hpp>
23 #include <boost/msm/common.hpp>
24 #include <boost/msm/front/completion_event.hpp>
26 #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
28 BOOST_MPL_HAS_XXX_TRAIT_DEF(deferring_action)
29 BOOST_MPL_HAS_XXX_TRAIT_DEF(some_deferring_actions)
31 namespace boost { namespace msm { namespace front
33 template <class Func,class Enable=void>
34 struct get_functor_return_value
36 static const ::boost::msm::back::HandledEnum value = ::boost::msm::back::HANDLED_TRUE;
39 struct get_functor_return_value<Func,
40 typename ::boost::enable_if<
41 typename has_deferring_action<Func>::type
45 static const ::boost::msm::back::HandledEnum value = ::boost::msm::back::HANDLED_DEFERRED;
49 struct get_functor_return_value<Func,
50 typename ::boost::enable_if<
51 typename has_some_deferring_actions<Func>::type
55 static const ::boost::msm::back::HandledEnum value =
56 (Func::some_deferring_actions::value ? ::boost::msm::back::HANDLED_DEFERRED : ::boost::msm::back::HANDLED_TRUE );
58 template <class SOURCE,class EVENT,class TARGET,class ACTION=none,class GUARD=none>
61 typedef SOURCE Source;
63 typedef TARGET Target;
64 typedef ACTION Action;
67 typedef row_tag row_type_tag;
68 template <class EVT,class FSM,class SourceState,class TargetState,class AllStates>
69 static ::boost::msm::back::HandledEnum action_call(FSM& fsm,EVT const& evt,SourceState& src,TargetState& tgt, AllStates&)
71 // create functor, call it
72 Action()(evt,fsm,src,tgt);
73 return get_functor_return_value<Action>::value;
75 template <class EVT,class FSM,class SourceState,class TargetState,class AllStates>
76 static bool guard_call(FSM& fsm,EVT const& evt,SourceState& src,TargetState& tgt,AllStates&)
78 // create functor, call it
79 return Guard()(evt,fsm,src,tgt);
83 template<class SOURCE,class EVENT,class TARGET>
84 struct Row<SOURCE,EVENT,TARGET,none,none>
86 typedef SOURCE Source;
88 typedef TARGET Target;
91 // no action, no guard
92 typedef _row_tag row_type_tag;
94 template<class SOURCE,class EVENT,class TARGET,class ACTION>
95 struct Row<SOURCE,EVENT,TARGET,ACTION,none>
97 typedef SOURCE Source;
99 typedef TARGET Target;
100 typedef ACTION Action;
103 typedef a_row_tag row_type_tag;
104 template <class EVT,class FSM,class SourceState,class TargetState,class AllStates>
105 static ::boost::msm::back::HandledEnum action_call(FSM& fsm,EVT const& evt,SourceState& src,TargetState& tgt, AllStates&)
107 // create functor, call it
108 Action()(evt,fsm,src,tgt);
109 return get_functor_return_value<Action>::value;
112 template<class SOURCE,class EVENT,class TARGET,class GUARD>
113 struct Row<SOURCE,EVENT,TARGET,none,GUARD>
115 typedef SOURCE Source;
117 typedef TARGET Target;
121 typedef g_row_tag row_type_tag;
122 template <class EVT,class FSM,class SourceState,class TargetState,class AllStates>
123 static bool guard_call(FSM& fsm,EVT const& evt,SourceState& src,TargetState& tgt, AllStates&)
125 // create functor, call it
126 return Guard()(evt,fsm,src,tgt);
129 // internal transitions
130 template<class SOURCE,class EVENT,class ACTION>
131 struct Row<SOURCE,EVENT,none,ACTION,none>
133 typedef SOURCE Source;
135 typedef Source Target;
136 typedef ACTION Action;
139 typedef a_irow_tag row_type_tag;
140 template <class EVT,class FSM,class SourceState,class TargetState,class AllStates>
141 static ::boost::msm::back::HandledEnum action_call(FSM& fsm,EVT const& evt,SourceState& src,TargetState& tgt, AllStates&)
143 // create functor, call it
144 Action()(evt,fsm,src,tgt);
145 return get_functor_return_value<Action>::value;
148 template<class SOURCE,class EVENT,class GUARD>
149 struct Row<SOURCE,EVENT,none,none,GUARD>
151 typedef SOURCE Source;
153 typedef Source Target;
157 typedef g_irow_tag row_type_tag;
158 template <class EVT,class FSM,class SourceState,class TargetState,class AllStates>
159 static bool guard_call(FSM& fsm,EVT const& evt,SourceState& src,TargetState& tgt, AllStates&)
161 // create functor, call it
162 return Guard()(evt,fsm,src,tgt);
165 template<class SOURCE,class EVENT,class ACTION,class GUARD>
166 struct Row<SOURCE,EVENT,none,ACTION,GUARD>
168 typedef SOURCE Source;
170 typedef Source Target;
171 typedef ACTION Action;
174 typedef irow_tag row_type_tag;
175 template <class EVT,class FSM,class SourceState,class TargetState,class AllStates>
176 static ::boost::msm::back::HandledEnum action_call(FSM& fsm,EVT const& evt,SourceState& src,TargetState& tgt, AllStates&)
178 // create functor, call it
179 Action()(evt,fsm,src,tgt);
180 return get_functor_return_value<Action>::value;
182 template <class EVT,class FSM,class SourceState,class TargetState,class AllStates>
183 static bool guard_call(FSM& fsm,EVT const& evt,SourceState& src,TargetState& tgt, AllStates&)
185 // create functor, call it
186 return Guard()(evt,fsm,src,tgt);
189 template<class SOURCE,class EVENT>
190 struct Row<SOURCE,EVENT,none,none,none>
192 typedef SOURCE Source;
194 typedef Source Target;
197 // no action, no guard
198 typedef _irow_tag row_type_tag;
201 struct get_row_target
203 typedef typename TGT::Target type;
206 template <class EVENT,class ACTION=none,class GUARD=none>
210 typedef ACTION Action;
213 typedef sm_i_row_tag row_type_tag;
214 template <class EVT,class FSM,class SourceState,class TargetState,class AllStates>
215 static ::boost::msm::back::HandledEnum action_call(FSM& fsm,EVT const& evt,SourceState& src,TargetState& tgt, AllStates&)
217 // create functor, call it
218 Action()(evt,fsm,src,tgt);
219 return get_functor_return_value<Action>::value;
221 template <class EVT,class FSM,class SourceState,class TargetState,class AllStates>
222 static bool guard_call(FSM& fsm,EVT const& evt,SourceState& src,TargetState& tgt, AllStates&)
224 // create functor, call it
225 return Guard()(evt,fsm,src,tgt);
229 template<class EVENT,class ACTION>
230 struct Internal<EVENT,ACTION,none>
233 typedef ACTION Action;
236 typedef sm_a_i_row_tag row_type_tag;
237 template <class EVT,class FSM,class SourceState,class TargetState,class AllStates>
238 static ::boost::msm::back::HandledEnum action_call(FSM& fsm,EVT const& evt,SourceState& src,TargetState& tgt, AllStates&)
240 // create functor, call it
241 Action()(evt,fsm,src,tgt);
242 return get_functor_return_value<Action>::value;
245 template<class EVENT,class GUARD>
246 struct Internal<EVENT,none,GUARD>
252 typedef sm_g_i_row_tag row_type_tag;
253 template <class EVT,class FSM,class SourceState,class TargetState,class AllStates>
254 static bool guard_call(FSM& fsm,EVT const& evt,SourceState& src,TargetState& tgt, AllStates&)
256 // create functor, call it
257 return Guard()(evt,fsm,src,tgt);
260 template<class EVENT>
261 struct Internal<EVENT,none,none>
266 // no action, no guard
267 typedef sm__i_row_tag row_type_tag;
271 struct state_action_tag{};
274 struct not_euml_tag{};
276 template <class Sequence>
277 struct ActionSequence_
279 typedef Sequence sequence;
280 // if one functor of the sequence defers events, the complete sequence does
281 typedef ::boost::mpl::bool_<
282 ::boost::mpl::count_if<sequence,
283 has_deferring_action< ::boost::mpl::placeholders::_1 >
284 >::value != 0> some_deferring_actions;
286 template <class Event,class FSM,class STATE >
287 struct state_action_result
291 template <class EVT,class FSM,class STATE>
294 Call(EVT const& evt,FSM& fsm,STATE& state):
295 evt_(evt),fsm_(fsm),state_(state){}
297 void operator()(::boost::msm::wrap<FCT> const& )
299 FCT()(evt_,fsm_,state_);
306 template <class EVT,class FSM,class SourceState,class TargetState>
307 struct transition_action_result
311 template <class EVT,class FSM,class SourceState,class TargetState>
314 Call2(EVT const& evt,FSM& fsm,SourceState& src,TargetState& tgt):
315 evt_(evt),fsm_(fsm),src_(src),tgt_(tgt){}
317 void operator()(::boost::msm::wrap<FCT> const& )
319 FCT()(evt_,fsm_,src_,tgt_);
328 typedef ::boost::mpl::set<state_action_tag,action_tag> tag_type;
330 template <class EVT,class FSM,class STATE>
331 void operator()(EVT const& evt,FSM& fsm,STATE& state)
333 mpl::for_each<Sequence,boost::msm::wrap< ::boost::mpl::placeholders::_1> >
334 (Call<EVT,FSM,STATE>(evt,fsm,state));
336 template <class EVT,class FSM,class SourceState,class TargetState>
337 void operator()(EVT const& evt,FSM& fsm,SourceState& src,TargetState& tgt)
339 mpl::for_each<Sequence,boost::msm::wrap< ::boost::mpl::placeholders::_1> >
340 (Call2<EVT,FSM,SourceState,TargetState>(evt,fsm,src,tgt));
344 // functor pre-defined for basic functionality
347 // mark as deferring to avoid stack overflows in certain conditions
348 typedef int deferring_action;
349 template <class EVT,class FSM,class SourceState,class TargetState>
350 void operator()(EVT const& evt,FSM& fsm,SourceState& ,TargetState& ) const
352 fsm.defer_event(evt);
356 #endif //BOOST_MSM_FRONT_FUNCTOR_ROW_H