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