SimpleTutorialWithEumlTableKleene.cpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. #include <iostream>
  2. // back-end
  3. #include <boost/msm/back/state_machine.hpp>
  4. //front-end
  5. #include <boost/msm/front/state_machine_def.hpp>
  6. #include <boost/msm/front/euml/euml.hpp>
  7. namespace msm = boost::msm;
  8. namespace mpl = boost::mpl;
  9. using namespace std;
  10. using namespace msm::front::euml;
  11. // entry/exit/action/guard logging functors
  12. #include "logging_functors.h"
  13. namespace
  14. {
  15. // events
  16. struct play_impl : msm::front::euml::euml_event<play_impl> {};
  17. struct end_pause_impl : msm::front::euml::euml_event<end_pause_impl>{};
  18. struct stop_impl : msm::front::euml::euml_event<stop_impl>{};
  19. struct pause_impl : msm::front::euml::euml_event<pause_impl>{};
  20. struct open_close_impl : msm::front::euml::euml_event<open_close_impl>{};
  21. struct cd_detected_impl : msm::front::euml::euml_event<cd_detected_impl>{};
  22. // define some dummy instances for use in the transition table
  23. // it is also possible to default-construct them instead:
  24. // struct play {};
  25. // inside the table: play()
  26. play_impl play;
  27. end_pause_impl end_pause;
  28. stop_impl stop;
  29. pause_impl pause;
  30. open_close_impl open_close;
  31. cd_detected_impl cd_detected;
  32. // The list of FSM states
  33. // they have to be declared outside of the front-end only to make VC happy :(
  34. // note: gcc would have no problem
  35. struct Empty_impl : public msm::front::state<> , public msm::front::euml::euml_state<Empty_impl>
  36. {
  37. // every (optional) entry/exit methods get the event passed.
  38. template <class Event,class FSM>
  39. void on_entry(Event const&,FSM& ) {std::cout << "entering: Empty" << std::endl;}
  40. template <class Event,class FSM>
  41. void on_exit(Event const&,FSM& ) {std::cout << "leaving: Empty" << std::endl;}
  42. };
  43. struct Open_impl : public msm::front::state<> , public msm::front::euml::euml_state<Open_impl>
  44. {
  45. template <class Event,class FSM>
  46. void on_entry(Event const& ,FSM&) {std::cout << "entering: Open" << std::endl;}
  47. template <class Event,class FSM>
  48. void on_exit(Event const&,FSM& ) {std::cout << "leaving: Open" << std::endl;}
  49. };
  50. struct Stopped_impl : public msm::front::state<> , public msm::front::euml::euml_state<Stopped_impl>
  51. {
  52. template <class Event,class FSM>
  53. void on_entry(Event const& ,FSM&) {std::cout << "entering: Stopped" << std::endl;}
  54. template <class Event,class FSM>
  55. void on_exit(Event const&,FSM& ) {std::cout << "leaving: Stopped" << std::endl;}
  56. };
  57. struct Playing_impl : public msm::front::state<> , public msm::front::euml::euml_state<Playing_impl>
  58. {
  59. template <class Event,class FSM>
  60. void on_entry(Event const&,FSM& ) {std::cout << "entering: Playing" << std::endl;}
  61. template <class Event,class FSM>
  62. void on_exit(Event const&,FSM& ) {std::cout << "leaving: Playing" << std::endl;}
  63. };
  64. // state not defining any entry or exit
  65. struct Paused_impl : public msm::front::state<> , public msm::front::euml::euml_state<Paused_impl>
  66. {
  67. };
  68. //to make the transition table more readable
  69. Empty_impl const Empty;
  70. Open_impl const Open;
  71. Stopped_impl const Stopped;
  72. Playing_impl const Playing;
  73. Paused_impl const Paused;
  74. BOOST_MSM_EUML_ACTION(pause_playback2)
  75. {
  76. template <class FSM,class EVT,class SourceState,class TargetState>
  77. void operator()(EVT const& evt,FSM&,SourceState& ,TargetState& )
  78. {
  79. cout << "player::pause_playback2" << endl;
  80. std::cout << "event type: " << typeid(EVT).name() << std::endl;
  81. std::cout << "pause_playback2 with any event: " << evt.type().name() << std::endl;
  82. }
  83. };
  84. // front-end: define the FSM structure
  85. struct player_ : public msm::front::state_machine_def<player_>
  86. {
  87. // the initial state of the player SM. Must be defined
  88. typedef Empty_impl initial_state;
  89. // Transition table for player
  90. // replaces the old transition table
  91. BOOST_MSM_EUML_DECLARE_TRANSITION_TABLE((
  92. Stopped + play / start_playback == Playing ,
  93. Stopped + open_close / open_drawer == Open ,
  94. Stopped + stop == Stopped ,
  95. // +------------------------------------------------------------------------------+
  96. Open + open_close / close_drawer == Empty ,
  97. // +------------------------------------------------------------------------------+
  98. Empty + open_close / open_drawer == Open ,
  99. Empty + cd_detected /(store_cd_info,
  100. msm::front::euml::process_(play)) == Stopped ,
  101. // +------------------------------------------------------------------------------+
  102. Playing + stop / stop_playback == Stopped ,
  103. Playing + kleene / pause_playback2 == Paused ,
  104. Playing + open_close / stop_and_open == Open ,
  105. // +------------------------------------------------------------------------------+
  106. Paused + end_pause / resume_playback == Playing ,
  107. Paused + stop / stop_playback == Stopped ,
  108. Paused + open_close / stop_and_open == Open
  109. // +------------------------------------------------------------------------------+
  110. ),transition_table)
  111. // Replaces the default no-transition response.
  112. template <class FSM,class Event>
  113. void no_transition(Event const& e, FSM&,int state)
  114. {
  115. std::cout << "no transition from state " << state
  116. << " on event " << typeid(e).name() << std::endl;
  117. }
  118. };
  119. // Pick a back-end
  120. typedef msm::back::state_machine<player_> player;
  121. //
  122. // Testing utilities.
  123. //
  124. static char const* const state_names[] = { "Stopped", "Open", "Empty", "Playing", "Paused" };
  125. void pstate(player const& p)
  126. {
  127. std::cout << " -> " << state_names[p.current_state()[0]] << std::endl;
  128. }
  129. void test()
  130. {
  131. player p;
  132. // needed to start the highest-level SM. This will call on_entry and mark the start of the SM
  133. p.start();
  134. // go to Open, call on_exit on Empty, then action, then on_entry on Open
  135. p.process_event(open_close); pstate(p);
  136. p.process_event(open_close); pstate(p);
  137. p.process_event(cd_detected); pstate(p);
  138. // at this point, Play is active
  139. p.process_event(pause); pstate(p);
  140. // go back to Playing
  141. p.process_event(end_pause); pstate(p);
  142. p.process_event(pause); pstate(p);
  143. p.process_event(stop); pstate(p);
  144. // event leading to the same state
  145. // no action method called as it is not present in the transition table
  146. p.process_event(stop); pstate(p);
  147. }
  148. }
  149. int main()
  150. {
  151. test();
  152. return 0;
  153. }