SimpleTutorialWithEumlTable.cpp 6.6 KB

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