• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
8 namespace msm = boost::msm;
9 namespace mpl = boost::mpl;
10 using namespace std;
11 
12 // entry/exit/action/guard logging functors
13 #include "logging_functors.h"
14 
15 namespace
16 {
17     // events
18     struct play_impl : msm::front::euml::euml_event<play_impl> {};
19     struct end_pause_impl : msm::front::euml::euml_event<end_pause_impl>{};
20     struct stop_impl : msm::front::euml::euml_event<stop_impl>{};
21     struct pause_impl : msm::front::euml::euml_event<pause_impl>{};
22     struct open_close_impl : msm::front::euml::euml_event<open_close_impl>{};
23     struct cd_detected_impl : msm::front::euml::euml_event<cd_detected_impl>{};
24     struct next_song_impl : msm::front::euml::euml_event<next_song_impl>{};
25     struct previous_song_impl : msm::front::euml::euml_event<previous_song_impl>{};
26 
27     // define some dummy instances for use in the transition table
28     // it is also possible to default-construct them instead:
29     // struct play {};
30     // inside the table: play()
31     play_impl play;
32     end_pause_impl end_pause;
33     stop_impl stop;
34     pause_impl pause;
35     open_close_impl open_close;
36     cd_detected_impl cd_detected;
37     next_song_impl next_song;
38     previous_song_impl previous_song;
39 
40     // The list of FSM states
41     // they have to be declared outside of the front-end only to make VC happy :(
42     // note: gcc would have no problem
43     struct Empty_impl : public msm::front::state<> , public msm::front::euml::euml_state<Empty_impl>
44     {
45         // every (optional) entry/exit methods get the event passed.
46         template <class Event,class FSM>
on_entry__anon9e6460780111::Empty_impl47         void on_entry(Event const&,FSM& ) {std::cout << "entering: Empty" << std::endl;}
48         template <class Event,class FSM>
on_exit__anon9e6460780111::Empty_impl49         void on_exit(Event const&,FSM& ) {std::cout << "leaving: Empty" << std::endl;}
50     };
51     struct Open_impl : public msm::front::state<> , public msm::front::euml::euml_state<Open_impl>
52     {
53         template <class Event,class FSM>
on_entry__anon9e6460780111::Open_impl54         void on_entry(Event const& ,FSM&) {std::cout << "entering: Open" << std::endl;}
55         template <class Event,class FSM>
on_exit__anon9e6460780111::Open_impl56         void on_exit(Event const&,FSM& ) {std::cout << "leaving: Open" << std::endl;}
57     };
58 
59     struct Stopped_impl : public msm::front::state<> , public msm::front::euml::euml_state<Stopped_impl>
60     {
61         template <class Event,class FSM>
on_entry__anon9e6460780111::Stopped_impl62         void on_entry(Event const& ,FSM&) {std::cout << "entering: Stopped" << std::endl;}
63         template <class Event,class FSM>
on_exit__anon9e6460780111::Stopped_impl64         void on_exit(Event const&,FSM& ) {std::cout << "leaving: Stopped" << std::endl;}
65     };
66 
67     // Playing Submachine front-end
68     struct Playing_ : public msm::front::state_machine_def<Playing_>
69     {
70         template <class Event,class FSM>
on_entry__anon9e6460780111::Playing_71         void on_entry(Event const& ,FSM&) {std::cout << "entering: Playing" << std::endl;}
72         template <class Event,class FSM>
on_exit__anon9e6460780111::Playing_73         void on_exit(Event const&,FSM& ) {std::cout << "leaving: Playing" << std::endl;}
74 
75         struct Song1_ : public msm::front::state<> , public msm::front::euml::euml_state<Song1_>
76         {
77             template <class Event,class FSM>
on_entry__anon9e6460780111::Playing_::Song1_78             void on_entry(Event const& ,FSM&) {std::cout << "entering: Song1" << std::endl;}
79             template <class Event,class FSM>
on_exit__anon9e6460780111::Playing_::Song1_80             void on_exit(Event const&,FSM& ) {std::cout << "leaving: Song1" << std::endl;}
81         };
82         struct Song2_ : public msm::front::state<> , public msm::front::euml::euml_state<Song2_>
83         {
84             template <class Event,class FSM>
on_entry__anon9e6460780111::Playing_::Song2_85             void on_entry(Event const& ,FSM&) {std::cout << "entering: Song2" << std::endl;}
86             template <class Event,class FSM>
on_exit__anon9e6460780111::Playing_::Song2_87             void on_exit(Event const&,FSM& ) {std::cout << "leaving: Song2" << std::endl;}
88         };
89         struct Song3_ : public msm::front::state<> , public msm::front::euml::euml_state<Song3_>
90         {
91             template <class Event,class FSM>
on_entry__anon9e6460780111::Playing_::Song3_92             void on_entry(Event const& ,FSM&) {std::cout << "entering: Song3" << std::endl;}
93             template <class Event,class FSM>
on_exit__anon9e6460780111::Playing_::Song3_94             void on_exit(Event const&,FSM& ) {std::cout << "leaving: Song3" << std::endl;}
95         };
96         // to make the transition table more readable
97         // VC seems to need them static
98         static Song1_ Song1;
99         static Song2_ Song2;
100         static Song3_ Song3;
101         typedef Song1_ initial_state;
102 
103         // Playing has a transition table
104         BOOST_MSM_EUML_DECLARE_TRANSITION_TABLE((
105         //  +------------------------------------------------------------------------------+
106             Song2         == Song1          + next_song       / start_next_song,
107             Song1         == Song2          + previous_song   / start_prev_song,
108             Song3         == Song2          + next_song       / start_next_song,
109             Song2         == Song3          + previous_song   / start_prev_song
110         //  +------------------------------------------------------------------------------+
111         ),transition_table )
112 
113     };
114     // Playing Submachine back-end
115     typedef boost::msm::back::state_machine<Playing_> Playing_impl;
116 
117     // state not defining any entry or exit
118     struct Paused_impl : public msm::front::state<> , public msm::front::euml::euml_state<Paused_impl>
119     {
120     };
121     //to make the transition table more readable
122     Empty_impl const Empty;
123     Open_impl const Open;
124     Stopped_impl const Stopped;
125     Playing_impl const Playing;
126     Paused_impl const Paused;
127 
128     // front-end: define the FSM structure
129     struct player_ : public msm::front::state_machine_def<player_>
130     {
131 
132         // the initial state of the player SM. Must be defined
133         typedef Empty_impl initial_state;
134 
135         // Transition table for player
136         // replaces the old transition table
137         BOOST_MSM_EUML_DECLARE_TRANSITION_TABLE((
138           Stopped + play        / start_playback                    == Playing               ,
139           Stopped + open_close  / open_drawer                       == Open                  ,
140           Stopped + stop                                            == Stopped               ,
141           //  +------------------------------------------------------------------------------+
142           Open    + open_close  / close_drawer                      == Empty                 ,
143           //  +------------------------------------------------------------------------------+
144           Empty   + open_close  / open_drawer                       == Open                  ,
145           Empty   + cd_detected /(store_cd_info,
146                                   msm::front::euml::process_(play)) == Stopped               ,
147           //  +------------------------------------------------------------------------------+
148           Playing + stop        / stop_playback                     == Stopped               ,
149           Playing + pause       / pause_playback                    == Paused                ,
150           Playing + open_close  / stop_and_open                     == Open                  ,
151           //  +------------------------------------------------------------------------------+
152           Paused  + end_pause   / resume_playback                   == Playing               ,
153           Paused  + stop        / stop_playback                     == Stopped               ,
154           Paused  + open_close  / stop_and_open                     == Open
155           //  +------------------------------------------------------------------------------+
156           ),transition_table)
157 
158         // Replaces the default no-transition response.
159         template <class FSM,class Event>
no_transition__anon9e6460780111::player_160         void no_transition(Event const& e, FSM&,int state)
161         {
162             std::cout << "no transition from state " << state
163                 << " on event " << typeid(e).name() << std::endl;
164         }
165     };
166     // Pick a back-end
167     typedef msm::back::state_machine<player_> player;
168 
169     //
170     // Testing utilities.
171     //
172     static char const* const state_names[] = { "Stopped", "Open", "Empty", "Playing", "Paused" };
pstate(player const & p)173     void pstate(player const& p)
174     {
175         std::cout << " -> " << state_names[p.current_state()[0]] << std::endl;
176     }
177 
test()178     void test()
179     {
180 		player p;
181         // needed to start the highest-level SM. This will call on_entry and mark the start of the SM
182         p.start();
183         // go to Open, call on_exit on Empty, then action, then on_entry on Open
184         p.process_event(open_close); pstate(p);
185         p.process_event(open_close); pstate(p);
186         p.process_event(cd_detected); pstate(p);
187 
188         // at this point, Play is active
189         // make transition happen inside it. Player has no idea about this event but it's ok.
190         p.process_event(next_song);pstate(p); //2nd song active
191         p.process_event(next_song);pstate(p);//3rd song active
192         p.process_event(previous_song);pstate(p);//2nd song active
193 
194         p.process_event(pause); pstate(p);
195         // go back to Playing
196         p.process_event(end_pause);  pstate(p);
197         p.process_event(pause); pstate(p);
198         p.process_event(stop);  pstate(p);
199         // event leading to the same state
200         // no action method called as it is not present in the transition table
201         p.process_event(stop);  pstate(p);
202     }
203 }
204 
main()205 int main()
206 {
207     test();
208     return 0;
209 }
210