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