summaryrefslogtreecommitdiff
path: root/libs/msm/doc/HTML/examples/CompositeTutorialWithEumlTable.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/msm/doc/HTML/examples/CompositeTutorialWithEumlTable.cpp')
-rw-r--r--libs/msm/doc/HTML/examples/CompositeTutorialWithEumlTable.cpp213
1 files changed, 213 insertions, 0 deletions
diff --git a/libs/msm/doc/HTML/examples/CompositeTutorialWithEumlTable.cpp b/libs/msm/doc/HTML/examples/CompositeTutorialWithEumlTable.cpp
new file mode 100644
index 0000000000..7783d2cdf6
--- /dev/null
+++ b/libs/msm/doc/HTML/examples/CompositeTutorialWithEumlTable.cpp
@@ -0,0 +1,213 @@
+#include <iostream>
+// back-end
+#include <boost/msm/back/state_machine.hpp>
+//front-end
+#include <boost/msm/front/state_machine_def.hpp>
+#include <boost/msm/front/euml/euml.hpp>
+
+namespace msm = boost::msm;
+namespace mpl = boost::mpl;
+using namespace std;
+
+// entry/exit/action/guard logging functors
+#include "logging_functors.h"
+
+namespace
+{
+ // events
+ struct play_impl : msm::front::euml::euml_event<play_impl> {};
+ struct end_pause_impl : msm::front::euml::euml_event<end_pause_impl>{};
+ struct stop_impl : msm::front::euml::euml_event<stop_impl>{};
+ struct pause_impl : msm::front::euml::euml_event<pause_impl>{};
+ struct open_close_impl : msm::front::euml::euml_event<open_close_impl>{};
+ struct cd_detected_impl : msm::front::euml::euml_event<cd_detected_impl>{};
+ struct next_song_impl : msm::front::euml::euml_event<next_song_impl>{};
+ struct previous_song_impl : msm::front::euml::euml_event<previous_song_impl>{};
+
+ // define some dummy instances for use in the transition table
+ // it is also possible to default-construct them instead:
+ // struct play {};
+ // inside the table: play()
+ play_impl play;
+ end_pause_impl end_pause;
+ stop_impl stop;
+ pause_impl pause;
+ open_close_impl open_close;
+ cd_detected_impl cd_detected;
+ next_song_impl next_song;
+ previous_song_impl previous_song;
+
+ // The list of FSM states
+ // they have to be declared outside of the front-end only to make VC happy :(
+ // note: gcc would have no problem
+ struct Empty_impl : public msm::front::state<> , public msm::front::euml::euml_state<Empty_impl>
+ {
+ // every (optional) entry/exit methods get the event passed.
+ template <class Event,class FSM>
+ void on_entry(Event const&,FSM& ) {std::cout << "entering: Empty" << std::endl;}
+ template <class Event,class FSM>
+ void on_exit(Event const&,FSM& ) {std::cout << "leaving: Empty" << std::endl;}
+ };
+ struct Open_impl : public msm::front::state<> , public msm::front::euml::euml_state<Open_impl>
+ {
+ template <class Event,class FSM>
+ void on_entry(Event const& ,FSM&) {std::cout << "entering: Open" << std::endl;}
+ template <class Event,class FSM>
+ void on_exit(Event const&,FSM& ) {std::cout << "leaving: Open" << std::endl;}
+ };
+
+ struct Stopped_impl : public msm::front::state<> , public msm::front::euml::euml_state<Stopped_impl>
+ {
+ template <class Event,class FSM>
+ void on_entry(Event const& ,FSM&) {std::cout << "entering: Stopped" << std::endl;}
+ template <class Event,class FSM>
+ void on_exit(Event const&,FSM& ) {std::cout << "leaving: Stopped" << std::endl;}
+ };
+
+ // Playing Submachine front-end
+ struct Playing_ : public msm::front::state_machine_def<Playing_>
+ {
+ template <class Event,class FSM>
+ void on_entry(Event const& ,FSM&) {std::cout << "entering: Playing" << std::endl;}
+ template <class Event,class FSM>
+ void on_exit(Event const&,FSM& ) {std::cout << "leaving: Playing" << std::endl;}
+
+ struct Song1_ : public msm::front::state<> , public msm::front::euml::euml_state<Song1_>
+ {
+ template <class Event,class FSM>
+ void on_entry(Event const& ,FSM&) {std::cout << "entering: Song1" << std::endl;}
+ template <class Event,class FSM>
+ void on_exit(Event const&,FSM& ) {std::cout << "leaving: Song1" << std::endl;}
+ };
+ struct Song2_ : public msm::front::state<> , public msm::front::euml::euml_state<Song2_>
+ {
+ template <class Event,class FSM>
+ void on_entry(Event const& ,FSM&) {std::cout << "entering: Song2" << std::endl;}
+ template <class Event,class FSM>
+ void on_exit(Event const&,FSM& ) {std::cout << "leaving: Song2" << std::endl;}
+ };
+ struct Song3_ : public msm::front::state<> , public msm::front::euml::euml_state<Song3_>
+ {
+ template <class Event,class FSM>
+ void on_entry(Event const& ,FSM&) {std::cout << "entering: Song3" << std::endl;}
+ template <class Event,class FSM>
+ void on_exit(Event const&,FSM& ) {std::cout << "leaving: Song3" << std::endl;}
+ };
+ // to make the transition table more readable
+ // VC seems to need them static
+ static Song1_ Song1;
+ static Song2_ Song2;
+ static Song3_ Song3;
+ typedef Song1_ initial_state;
+
+ // Playing has a transition table
+ BOOST_MSM_EUML_DECLARE_TRANSITION_TABLE((
+ // +------------------------------------------------------------------------------+
+ Song2 == Song1 + next_song / start_next_song,
+ Song1 == Song2 + previous_song / start_prev_song,
+ Song3 == Song2 + next_song / start_next_song,
+ Song2 == Song3 + previous_song / start_prev_song
+ // +------------------------------------------------------------------------------+
+ ),transition_table )
+
+ };
+ // Playing Submachine back-end
+ typedef boost::msm::back::state_machine<Playing_> Playing_helper;
+ struct Playing_impl : public Playing_helper,
+ public msm::front::euml::euml_state<Playing_helper>
+ {
+ };
+
+ // state not defining any entry or exit
+ struct Paused_impl : public msm::front::state<> , public msm::front::euml::euml_state<Paused_impl>
+ {
+ };
+ //to make the transition table more readable
+ Empty_impl const Empty;
+ Open_impl const Open;
+ Stopped_impl const Stopped;
+ Playing_impl const Playing;
+ Paused_impl const Paused;
+
+ // front-end: define the FSM structure
+ struct player_ : public msm::front::state_machine_def<player_>
+ {
+
+ // the initial state of the player SM. Must be defined
+ typedef Empty_impl initial_state;
+
+ // Transition table for player
+ // replaces the old transition table
+ BOOST_MSM_EUML_DECLARE_TRANSITION_TABLE((
+ Stopped + play / start_playback == Playing ,
+ Stopped + open_close / open_drawer == Open ,
+ Stopped + stop == Stopped ,
+ // +------------------------------------------------------------------------------+
+ Open + open_close / close_drawer == Empty ,
+ // +------------------------------------------------------------------------------+
+ Empty + open_close / open_drawer == Open ,
+ Empty + cd_detected /(store_cd_info,
+ msm::front::euml::process_(play)) == Stopped ,
+ // +------------------------------------------------------------------------------+
+ Playing + stop / stop_playback == Stopped ,
+ Playing + pause / pause_playback == Paused ,
+ Playing + open_close / stop_and_open == Open ,
+ // +------------------------------------------------------------------------------+
+ Paused + end_pause / resume_playback == Playing ,
+ Paused + stop / stop_playback == Stopped ,
+ Paused + open_close / stop_and_open == Open
+ // +------------------------------------------------------------------------------+
+ ),transition_table)
+
+ // Replaces the default no-transition response.
+ template <class FSM,class Event>
+ void no_transition(Event const& e, FSM&,int state)
+ {
+ std::cout << "no transition from state " << state
+ << " on event " << typeid(e).name() << std::endl;
+ }
+ };
+ // Pick a back-end
+ typedef msm::back::state_machine<player_> player;
+
+ //
+ // Testing utilities.
+ //
+ static char const* const state_names[] = { "Stopped", "Open", "Empty", "Playing", "Paused" };
+ void pstate(player const& p)
+ {
+ std::cout << " -> " << state_names[p.current_state()[0]] << std::endl;
+ }
+
+ void test()
+ {
+ player p;
+ // needed to start the highest-level SM. This will call on_entry and mark the start of the SM
+ p.start();
+ // go to Open, call on_exit on Empty, then action, then on_entry on Open
+ p.process_event(open_close); pstate(p);
+ p.process_event(open_close); pstate(p);
+ p.process_event(cd_detected); pstate(p);
+
+ // at this point, Play is active
+ // make transition happen inside it. Player has no idea about this event but it's ok.
+ p.process_event(next_song);pstate(p); //2nd song active
+ p.process_event(next_song);pstate(p);//3rd song active
+ p.process_event(previous_song);pstate(p);//2nd song active
+
+ p.process_event(pause); pstate(p);
+ // go back to Playing
+ p.process_event(end_pause); pstate(p);
+ p.process_event(pause); pstate(p);
+ p.process_event(stop); pstate(p);
+ // event leading to the same state
+ // no action method called as it is not present in the transition table
+ p.process_event(stop); pstate(p);
+ }
+}
+
+int main()
+{
+ test();
+ return 0;
+}