DirectEntryTutorial.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  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. // back-end
  13. #include <boost/msm/back/state_machine.hpp>
  14. //front-end
  15. #include <boost/msm/front/state_machine_def.hpp>
  16. namespace msm = boost::msm;
  17. namespace mpl = boost::mpl;
  18. namespace
  19. {
  20. // events
  21. struct event1 {};
  22. struct event2 {};
  23. struct event3 {};
  24. struct event4 {};
  25. struct event5 {};
  26. struct event6
  27. {
  28. event6(){}
  29. template <class Event>
  30. event6(Event const&){}
  31. };
  32. // front-end: define the FSM structure
  33. struct Fsm_ : public msm::front::state_machine_def<Fsm_>
  34. {
  35. // The list of FSM states
  36. struct State1 : public msm::front::state<>
  37. {
  38. // every (optional) entry/exit methods get the event passed.
  39. template <class Event,class FSM>
  40. void on_entry(Event const&,FSM& ) {std::cout << "entering: State1" << std::endl;}
  41. template <class Event,class FSM>
  42. void on_exit(Event const&,FSM& ) {std::cout << "leaving: State1" << std::endl;}
  43. };
  44. struct State2 : public msm::front::state<>
  45. {
  46. // every (optional) entry/exit methods get the event passed.
  47. template <class Event,class FSM>
  48. void on_entry(Event const&,FSM& ) {std::cout << "entering: State2" << std::endl;}
  49. template <class Event,class FSM>
  50. void on_exit(Event const&,FSM& ) {std::cout << "leaving: State2" << std::endl;}
  51. };
  52. struct SubFsm2_ : public msm::front::state_machine_def<SubFsm2_>
  53. {
  54. typedef msm::back::state_machine<SubFsm2_> SubFsm2;
  55. template <class Event,class FSM>
  56. void on_entry(Event const&,FSM& ) {std::cout << "entering: SubFsm2" << std::endl;}
  57. template <class Event,class FSM>
  58. void on_exit(Event const&,FSM& ) {std::cout << "leaving: SubFsm2" << std::endl;}
  59. struct SubState1 : public msm::front::state<>
  60. {
  61. template <class Event,class FSM>
  62. void on_entry(Event const&,FSM& ) {std::cout << "entering: SubFsm2::SubState1" << std::endl;}
  63. template <class Event,class FSM>
  64. void on_exit(Event const&,FSM& ) {std::cout << "leaving: SubFsm2::SubState1" << std::endl;}
  65. };
  66. struct SubState1b : public msm::front::state<>
  67. {
  68. template <class Event,class FSM>
  69. void on_entry(Event const&,FSM& ) {std::cout << "entering: SubFsm2::SubState1b" << std::endl;}
  70. template <class Event,class FSM>
  71. void on_exit(Event const&,FSM& ) {std::cout << "leaving: SubFsm2::SubState1b" << std::endl;}
  72. };
  73. struct SubState2 : public msm::front::state<> , public msm::front::explicit_entry<0>
  74. {
  75. template <class Event,class FSM>
  76. void on_entry(Event const&,FSM& ) {std::cout << "entering: SubFsm2::SubState2" << std::endl;}
  77. template <class Event,class FSM>
  78. void on_exit(Event const&,FSM& ) {std::cout << "leaving: SubFsm2::SubState2" << std::endl;}
  79. };
  80. struct SubState2b : public msm::front::state<> , public msm::front::explicit_entry<1>
  81. {
  82. template <class Event,class FSM>
  83. void on_entry(Event const&,FSM& ) {std::cout << "entering: SubFsm2::SubState2b" << std::endl;}
  84. template <class Event,class FSM>
  85. void on_exit(Event const&,FSM& ) {std::cout << "leaving: SubFsm2::SubState2b" << std::endl;}
  86. };
  87. // test with a pseudo entry
  88. struct PseudoEntry1 : public msm::front::entry_pseudo_state<0>
  89. {
  90. template <class Event,class FSM>
  91. void on_entry(Event const&,FSM& ) {std::cout << "entering: SubFsm2::PseudoEntry1" << std::endl;}
  92. template <class Event,class FSM>
  93. void on_exit(Event const&,FSM& ) {std::cout << "leaving: SubFsm2::PseudoEntry1" << std::endl;}
  94. };
  95. struct SubState3 : public msm::front::state<>
  96. {
  97. template <class Event,class FSM>
  98. void on_entry(Event const&,FSM& ) {std::cout << "entering: SubFsm2::SubState3" << std::endl;}
  99. template <class Event,class FSM>
  100. void on_exit(Event const&,FSM& ) {std::cout << "leaving: SubFsm2::SubState3" << std::endl;}
  101. };
  102. struct SubState3b : public msm::front::state<>
  103. {
  104. template <class Event,class FSM>
  105. void on_entry(Event const&,FSM& ) {std::cout << "entering: SubFsm2::SubState3b" << std::endl;}
  106. template <class Event,class FSM>
  107. void on_exit(Event const&,FSM& ) {std::cout << "leaving: SubFsm2::SubState3b" << std::endl;}
  108. };
  109. struct PseudoExit1 : public msm::front::exit_pseudo_state<event6>
  110. {
  111. template <class Event,class FSM>
  112. void on_entry(Event const&,FSM& ) {std::cout << "entering: SubFsm2::PseudoExit1" << std::endl;}
  113. template <class Event,class FSM>
  114. void on_exit(Event const&,FSM& ) {std::cout << "leaving: SubFsm2::PseudoExit1" << std::endl;}
  115. };
  116. // action methods
  117. void entry_action(event4 const&)
  118. {
  119. std::cout << "calling entry_action" << std::endl;
  120. }
  121. // the initial state. Must be defined
  122. typedef mpl::vector<SubState1,SubState1b> initial_state;
  123. typedef mpl::vector<SubState2b> explicit_creation;
  124. // Transition table for SubFsm2
  125. struct transition_table : mpl::vector<
  126. // Start Event Next Action Guard
  127. // +--------------+-------------+------------+------------------------+----------------------+
  128. a_row < PseudoEntry1 , event4 , SubState3 ,&SubFsm2_::entry_action >,
  129. _row < SubState2 , event6 , SubState1 >,
  130. _row < SubState3 , event5 , PseudoExit1 >
  131. // +--------------+-------------+------------+------------------------+----------------------+
  132. > {};
  133. // Replaces the default no-transition response.
  134. template <class FSM,class Event>
  135. void no_transition(Event const& e, FSM&,int state)
  136. {
  137. std::cout << "no transition from state " << state
  138. << " on event " << typeid(e).name() << std::endl;
  139. }
  140. };
  141. typedef msm::back::state_machine<SubFsm2_> SubFsm2;
  142. // the initial state of the player SM. Must be defined
  143. typedef State1 initial_state;
  144. // transition actions
  145. // guard conditions
  146. // Transition table for Fsm
  147. struct transition_table : mpl::vector<
  148. // Start Event Next Action Guard
  149. // +---------------------+--------+------------------------------------+-------+--------+
  150. _row < State1 , event1 , SubFsm2 >,
  151. _row < State1 , event2 , SubFsm2::direct<SubFsm2_::SubState2> >,
  152. _row < State1 , event3 , mpl::vector<SubFsm2::direct<SubFsm2_::SubState2>,
  153. SubFsm2::direct<SubFsm2_::SubState2b> > >,
  154. _row < State1 , event4 , SubFsm2::entry_pt
  155. <SubFsm2_::PseudoEntry1> >,
  156. // +---------------------+--------+------------------------------------+-------+--------+
  157. _row < SubFsm2 , event1 , State1 >,
  158. _row < SubFsm2::exit_pt
  159. <SubFsm2_::PseudoExit1>, event6 , State2 >
  160. // +---------------------+--------+------------------------------------+-------+--------+
  161. > {};
  162. // Replaces the default no-transition response.
  163. template <class FSM,class Event>
  164. void no_transition(Event const& e, FSM&,int state)
  165. {
  166. std::cout << "no transition from state " << state
  167. << " on event " << typeid(e).name() << std::endl;
  168. }
  169. };
  170. typedef msm::back::state_machine<Fsm_> Fsm;
  171. //
  172. // Testing utilities.
  173. //
  174. static char const* const state_names[] = { "State1", "SubFsm2","State2" };
  175. void pstate(Fsm const& p)
  176. {
  177. std::cout << " -> " << state_names[p.current_state()[0]] << std::endl;
  178. }
  179. void test()
  180. {
  181. Fsm p;
  182. // needed to start the highest-level SM. This will call on_entry and mark the start of the SM
  183. p.start();
  184. std::cout << "Simply move in and out of the composite, activate init states" << std::endl;
  185. p.process_event(event1()); pstate(p);
  186. p.process_event(event1()); pstate(p);
  187. std::cout << "Direct entry into SubFsm2::SubState2, then transition to SubState1 and back to State1" << std::endl;
  188. p.process_event(event2()); pstate(p);
  189. p.process_event(event6()); pstate(p);
  190. p.process_event(event1()); pstate(p);
  191. std::cout << "processing fork to SubFsm2::SubState2 and SubFsm2::SubState2b" << std::endl;
  192. p.process_event(event3()); pstate(p);
  193. p.process_event(event1()); pstate(p);
  194. std::cout << "processing entry pseudo state" << std::endl;
  195. p.process_event(event4()); pstate(p);
  196. p.process_event(event1()); pstate(p);
  197. std::cout << "processing entry + exit pseudo state" << std::endl;
  198. p.process_event(event4()); pstate(p);
  199. std::cout << "using exit pseudo state" << std::endl;
  200. p.process_event(event5()); pstate(p);
  201. }
  202. }
  203. int main()
  204. {
  205. test();
  206. return 0;
  207. }