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