DirectEntryEuml.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. // Copyright 2010 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. #include <vector>
  11. #include <iostream>
  12. #include <boost/msm/back/state_machine.hpp>
  13. #include <boost/msm/front/euml/euml.hpp>
  14. using namespace std;
  15. using namespace boost::msm::front::euml;
  16. namespace msm = boost::msm;
  17. namespace mpl = boost::mpl;
  18. namespace // Concrete FSM implementation
  19. {
  20. // events
  21. BOOST_MSM_EUML_EVENT(event1)
  22. BOOST_MSM_EUML_EVENT(event2)
  23. BOOST_MSM_EUML_EVENT(event3)
  24. BOOST_MSM_EUML_EVENT(event4)
  25. BOOST_MSM_EUML_EVENT(event5)
  26. // if we need something special, like a template constructor, we cannot use the helper macros
  27. struct event6_impl : euml_event<event6_impl>
  28. {
  29. event6_impl(){}
  30. template <class Event>
  31. event6_impl(Event const&){}
  32. };
  33. event6_impl const event6;
  34. //Sub fsm state definition
  35. BOOST_MSM_EUML_ACTION(SubState1_Entry)
  36. {
  37. template <class Event,class FSM,class STATE>
  38. void operator()(Event const&,FSM&,STATE& )
  39. {
  40. std::cout << "entering: SubFsm2::SubState1" << std::endl;
  41. }
  42. };
  43. BOOST_MSM_EUML_ACTION(SubState1_Exit)
  44. {
  45. template <class Event,class FSM,class STATE>
  46. void operator()(Event const&,FSM&,STATE& )
  47. {
  48. std::cout << "leaving: SubFsm2::SubState1" << std::endl;
  49. }
  50. };
  51. BOOST_MSM_EUML_STATE(( SubState1_Entry,SubState1_Exit ),SubState1)
  52. BOOST_MSM_EUML_ACTION(SubState1b_Entry)
  53. {
  54. template <class Event,class FSM,class STATE>
  55. void operator()(Event const&,FSM&,STATE& )
  56. {
  57. std::cout << "entering: SubFsm2::SubState1b" << std::endl;
  58. }
  59. };
  60. BOOST_MSM_EUML_ACTION(SubState1b_Exit)
  61. {
  62. template <class Event,class FSM,class STATE>
  63. void operator()(Event const&,FSM&,STATE& )
  64. {
  65. std::cout << "leaving: SubFsm2::SubState1b" << std::endl;
  66. }
  67. };
  68. BOOST_MSM_EUML_STATE(( SubState1b_Entry,SubState1b_Exit ),SubState1b)
  69. BOOST_MSM_EUML_ACTION(SubState1c_Entry)
  70. {
  71. template <class Event,class FSM,class STATE>
  72. void operator()(Event const&,FSM&,STATE& )
  73. {
  74. std::cout << "entering: SubFsm2::SubState1c" << std::endl;
  75. }
  76. };
  77. BOOST_MSM_EUML_ACTION(SubState1c_Exit)
  78. {
  79. template <class Event,class FSM,class STATE>
  80. void operator()(Event const&,FSM&,STATE& )
  81. {
  82. std::cout << "leaving: SubFsm2::SubState1c" << std::endl;
  83. }
  84. };
  85. BOOST_MSM_EUML_STATE(( SubState1c_Entry,SubState1c_Exit ),SubState1c)
  86. BOOST_MSM_EUML_ACTION(SubState2_Entry)
  87. {
  88. template <class Event,class FSM,class STATE>
  89. void operator()(Event const&,FSM&,STATE& )
  90. {
  91. std::cout << "entering: SubFsm2::SubState2" << std::endl;
  92. }
  93. };
  94. BOOST_MSM_EUML_ACTION(SubState2_Exit)
  95. {
  96. template <class Event,class FSM,class STATE>
  97. void operator()(Event const&,FSM&,STATE& )
  98. {
  99. std::cout << "leaving: SubFsm2::SubState2" << std::endl;
  100. }
  101. };
  102. BOOST_MSM_EUML_EXPLICIT_ENTRY_STATE(0,( SubState2_Entry,SubState2_Exit ),SubState2)
  103. BOOST_MSM_EUML_ACTION(SubState2b_Entry)
  104. {
  105. template <class Event,class FSM,class STATE>
  106. void operator()(Event const&,FSM&,STATE& )
  107. {
  108. std::cout << "entering: SubFsm2::SubState2b" << std::endl;
  109. }
  110. };
  111. BOOST_MSM_EUML_ACTION(SubState2b_Exit)
  112. {
  113. template <class Event,class FSM,class STATE>
  114. void operator()(Event const&,FSM&,STATE& )
  115. {
  116. std::cout << "leaving: SubFsm2::SubState2b" << std::endl;
  117. }
  118. };
  119. BOOST_MSM_EUML_EXPLICIT_ENTRY_STATE(1,( SubState2b_Entry,SubState2b_Exit ),SubState2b)
  120. BOOST_MSM_EUML_ACTION(SubState2c_Entry)
  121. {
  122. template <class Event,class FSM,class STATE>
  123. void operator()(Event const&,FSM&,STATE& )
  124. {
  125. std::cout << "entering: SubFsm2::SubState2c" << std::endl;
  126. }
  127. };
  128. BOOST_MSM_EUML_ACTION(SubState2c_Exit)
  129. {
  130. template <class Event,class FSM,class STATE>
  131. void operator()(Event const&,FSM&,STATE& )
  132. {
  133. std::cout << "leaving: SubFsm2::SubState2c" << std::endl;
  134. }
  135. };
  136. BOOST_MSM_EUML_EXPLICIT_ENTRY_STATE(2,( SubState2c_Entry,SubState2c_Exit ),SubState2c)
  137. BOOST_MSM_EUML_ACTION(PseudoEntry1_Entry)
  138. {
  139. template <class Event,class FSM,class STATE>
  140. void operator()(Event const&,FSM&,STATE& )
  141. {
  142. std::cout << "entering: SubFsm2::PseudoEntry1" << std::endl;
  143. }
  144. };
  145. BOOST_MSM_EUML_ACTION(PseudoEntry1_Exit)
  146. {
  147. template <class Event,class FSM,class STATE>
  148. void operator()(Event const&,FSM&,STATE& )
  149. {
  150. std::cout << "leaving: SubFsm2::PseudoEntry1" << std::endl;
  151. }
  152. };
  153. BOOST_MSM_EUML_ENTRY_STATE(0,( PseudoEntry1_Entry,PseudoEntry1_Exit ),PseudoEntry1)
  154. BOOST_MSM_EUML_ACTION(SubState3_Entry)
  155. {
  156. template <class Event,class FSM,class STATE>
  157. void operator()(Event const&,FSM&,STATE& )
  158. {
  159. std::cout << "entering: SubFsm2::SubState3" << std::endl;
  160. }
  161. };
  162. BOOST_MSM_EUML_ACTION(SubState3_Exit)
  163. {
  164. template <class Event,class FSM,class STATE>
  165. void operator()(Event const&,FSM&,STATE& )
  166. {
  167. std::cout << "leaving: SubFsm2::SubState3" << std::endl;
  168. }
  169. };
  170. BOOST_MSM_EUML_STATE(( SubState3_Entry,SubState3_Exit ),SubState3)
  171. BOOST_MSM_EUML_ACTION(SubState3b_Entry)
  172. {
  173. template <class Event,class FSM,class STATE>
  174. void operator()(Event const&,FSM&,STATE& )
  175. {
  176. std::cout << "entering: SubFsm2::SubState3b" << std::endl;
  177. }
  178. };
  179. BOOST_MSM_EUML_ACTION(SubState3b_Exit)
  180. {
  181. template <class Event,class FSM,class STATE>
  182. void operator()(Event const&,FSM&,STATE& )
  183. {
  184. std::cout << "leaving: SubFsm2::SubState3b" << std::endl;
  185. }
  186. };
  187. BOOST_MSM_EUML_STATE(( SubState3b_Entry,SubState3b_Exit ),SubState3b)
  188. BOOST_MSM_EUML_ACTION(PseudoExit1_Entry)
  189. {
  190. template <class Event,class FSM,class STATE>
  191. void operator()(Event const&,FSM&,STATE& )
  192. {
  193. std::cout << "entering: SubFsm2::PseudoExit1" << std::endl;
  194. }
  195. };
  196. BOOST_MSM_EUML_ACTION(PseudoExit1_Exit)
  197. {
  198. template <class Event,class FSM,class STATE>
  199. void operator()(Event const&,FSM&,STATE& )
  200. {
  201. std::cout << "leaving: SubFsm2::PseudoExit1" << std::endl;
  202. }
  203. };
  204. BOOST_MSM_EUML_EXIT_STATE(( event6,PseudoExit1_Entry,PseudoExit1_Exit ),PseudoExit1)
  205. // actions
  206. BOOST_MSM_EUML_ACTION(entry_action)
  207. {
  208. template <class FSM,class EVT,class SourceState,class TargetState>
  209. void operator()(FSM& ,EVT const& ,SourceState& ,TargetState& )
  210. {
  211. cout << "calling entry_action" << endl;
  212. }
  213. };
  214. // SubFsm definition
  215. BOOST_MSM_EUML_ACTION(SubFsm2_Entry)
  216. {
  217. template <class Event,class FSM,class STATE>
  218. void operator()(Event const&,FSM&,STATE& )
  219. {
  220. std::cout << "entering: SubFsm2" << std::endl;
  221. }
  222. };
  223. BOOST_MSM_EUML_ACTION(SubFsm2_Exit)
  224. {
  225. template <class Event,class FSM,class STATE>
  226. void operator()(Event const&,FSM&,STATE& )
  227. {
  228. std::cout << "leaving: SubFsm2" << std::endl;
  229. }
  230. };
  231. BOOST_MSM_EUML_TRANSITION_TABLE((
  232. // +------------------------------------------------------------------------------+
  233. SubState3 == PseudoEntry1 + event4 / entry_action ,
  234. SubState1 == SubState2 + event6 ,
  235. PseudoExit1 == SubState3 + event5
  236. // +------------------------------------------------------------------------------+
  237. ), SubFsm2_transition_table)
  238. BOOST_MSM_EUML_DECLARE_STATE_MACHINE( (SubFsm2_transition_table, //STT
  239. init_ << SubState1 << SubState1b << SubState1c, // Init State
  240. SubFsm2_Entry, // Entry
  241. SubFsm2_Exit
  242. ),SubFsm2_def)
  243. // inherit to add some typedef
  244. struct SubFsm2_ : public SubFsm2_def
  245. {
  246. // these 2 states are not found in the transition table because they are accessed only through
  247. // a fork, so we need to create them explicitly
  248. typedef mpl::vector<BOOST_MSM_EUML_STATE_NAME(SubState2b),
  249. BOOST_MSM_EUML_STATE_NAME(SubState2c)> explicit_creation;
  250. };
  251. // back-end
  252. typedef msm::back::state_machine<SubFsm2_> SubFsm2_type;
  253. SubFsm2_type const SubFsm2;
  254. // Fsm state definitions
  255. BOOST_MSM_EUML_ACTION(State1_Entry)
  256. {
  257. template <class Event,class FSM,class STATE>
  258. void operator()(Event const&,FSM&,STATE& )
  259. {
  260. std::cout << "entering: State1" << std::endl;
  261. }
  262. };
  263. BOOST_MSM_EUML_ACTION(State1_Exit)
  264. {
  265. template <class Event,class FSM,class STATE>
  266. void operator()(Event const&,FSM&,STATE& )
  267. {
  268. std::cout << "leaving: State1" << std::endl;
  269. }
  270. };
  271. BOOST_MSM_EUML_STATE(( State1_Entry,State1_Exit ),State1)
  272. BOOST_MSM_EUML_ACTION(State2_Entry)
  273. {
  274. template <class Event,class FSM,class STATE>
  275. void operator()(Event const&,FSM&,STATE& )
  276. {
  277. std::cout << "entering: State2" << std::endl;
  278. }
  279. };
  280. BOOST_MSM_EUML_ACTION(State2_Exit)
  281. {
  282. template <class Event,class FSM,class STATE>
  283. void operator()(Event const&,FSM&,STATE& )
  284. {
  285. std::cout << "leaving: State2" << std::endl;
  286. }
  287. };
  288. BOOST_MSM_EUML_STATE(( State2_Entry,State2_Exit ),State2)
  289. // Fsm definition
  290. BOOST_MSM_EUML_TRANSITION_TABLE((
  291. // +------------------------------------------------------------------------------+
  292. SubFsm2 == State1 + event1 ,
  293. explicit_(SubFsm2,SubState2) == State1 + event2,
  294. (explicit_(SubFsm2,SubState2),
  295. explicit_(SubFsm2,SubState2b),
  296. explicit_(SubFsm2,SubState2c)) == State1 + event3 ,
  297. entry_pt_(SubFsm2,PseudoEntry1) == State1 + event4 ,
  298. State1 == SubFsm2 + event1 ,
  299. State2 == exit_pt_
  300. (SubFsm2,PseudoExit1) + event6
  301. // +------------------------------------------------------------------------------+
  302. ),transition_table )
  303. BOOST_MSM_EUML_ACTION(Log_No_Transition)
  304. {
  305. template <class Event,class FSM,class STATE>
  306. void operator()(Event const& e,FSM&,STATE& )
  307. {
  308. std::cout << "no transition in Fsm"
  309. << " on event " << typeid(e).name() << std::endl;
  310. }
  311. };
  312. BOOST_MSM_EUML_DECLARE_STATE_MACHINE(( transition_table, //STT
  313. init_ << State1, // Init State
  314. no_action, // Entry
  315. no_action, // Exit
  316. attributes_ << no_attributes_, // Attributes
  317. configure_ << no_configure_, // configuration
  318. Log_No_Transition // no_transition handler
  319. ),
  320. Fsm_) //fsm name
  321. //back-end
  322. typedef msm::back::state_machine<Fsm_> Fsm;
  323. //
  324. // Testing utilities.
  325. //
  326. static char const* const state_names[] = { "State1", "SubFsm2","State2" };
  327. void pstate(Fsm const& p)
  328. {
  329. std::cout << " -> " << state_names[p.current_state()[0]] << std::endl;
  330. }
  331. void test()
  332. {
  333. Fsm p;
  334. // needed to start the highest-level SM. This will call on_entry and mark the start of the SM
  335. p.start();
  336. std::cout << "Simply move in and out of the composite, activate init states" << std::endl;
  337. p.process_event(event1); pstate(p);
  338. p.process_event(event1); pstate(p);
  339. std::cout << "Direct entry into SubFsm2::SubState2, then transition to SubState1 and back to State1" << std::endl;
  340. p.process_event(event2); pstate(p);
  341. p.process_event(event6); pstate(p);
  342. p.process_event(event1); pstate(p);
  343. std::cout << "processing fork to SubFsm2::SubState2, SubFsm2::SubState2b and SubFsm2::SubState2c" << std::endl;
  344. p.process_event(event3); pstate(p);
  345. p.process_event(event1); pstate(p);
  346. std::cout << "processing entry pseudo state" << std::endl;
  347. p.process_event(event4); pstate(p);
  348. p.process_event(event1); pstate(p);
  349. std::cout << "processing entry + exit pseudo state" << std::endl;
  350. p.process_event(event4); pstate(p);
  351. std::cout << "using exit pseudo state" << std::endl;
  352. p.process_event(event5); pstate(p);
  353. }
  354. }
  355. int main()
  356. {
  357. test();
  358. return 0;
  359. }