]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/msm/doc/HTML/examples/SimpleWithFunctors2.cpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / msm / doc / HTML / examples / SimpleWithFunctors2.cpp
1 // Copyright 2010 Christophe Henry
2 // henry UNDERSCORE christophe AT hotmail DOT com
3 // This is an extended version of the state machine available in the boost::mpl library
4 // Distributed under the same license as the original.
5 // Copyright for the original version:
6 // Copyright 2005 David Abrahams and Aleksey Gurtovoy. Distributed
7 // under the Boost Software License, Version 1.0. (See accompanying
8 // file LICENSE_1_0.txt or copy at
9 // http://www.boost.org/LICENSE_1_0.txt)
10
11 #include <vector>
12 #include <iostream>
13 // back-end
14 #include <boost/msm/back/state_machine.hpp>
15 //front-end
16 #include <boost/msm/front/state_machine_def.hpp>
17 // functors
18 #include <boost/msm/front/functor_row.hpp>
19 #include <boost/msm/front/euml/common.hpp>
20 // for And_ operator
21 #include <boost/msm/front/euml/operator.hpp>
22 // for func_state and func_state_machine
23 #include <boost/msm/front/euml/state_grammar.hpp>
24
25 using namespace std;
26 namespace msm = boost::msm;
27 namespace mpl = boost::mpl;
28 using namespace msm::front;
29 // for And_ operator
30 using namespace msm::front::euml;
31
32 namespace // Concrete FSM implementation
33 {
34 // events
35 struct play {};
36 struct end_pause {};
37 struct stop {};
38 struct pause {};
39 struct open_close {};
40
41 // A "complicated" event type that carries some data.
42 enum DiskTypeEnum
43 {
44 DISK_CD=0,
45 DISK_DVD=1
46 };
47 struct cd_detected
48 {
49 cd_detected(std::string name, DiskTypeEnum diskType)
50 : name(name),
51 disc_type(diskType)
52 {}
53
54 std::string name;
55 DiskTypeEnum disc_type;
56 };
57
58 // front-end: define the FSM structure
59 struct player_ : public msm::front::state_machine_def<player_>
60 {
61 // The list of FSM states
62 // entry and exit functors for Empty
63 struct Empty_Entry
64 {
65 template <class Event,class FSM,class STATE>
66 void operator()(Event const&,FSM&,STATE& )
67 {
68 std::cout << "entering: Empty" << std::endl;
69 }
70 };
71 struct Empty_Exit
72 {
73 template <class Event,class FSM,class STATE>
74 void operator()(Event const&,FSM&,STATE& )
75 {
76 std::cout << "leaving: Empty" << std::endl;
77 }
78 };
79 // definition of Empty
80 struct Empty_tag {};
81 typedef msm::front::euml::func_state<Empty_tag,Empty_Entry,Empty_Exit> Empty;
82
83 struct Open_Entry
84 {
85 template <class Event,class FSM,class STATE>
86 void operator()(Event const&,FSM&,STATE& )
87 {
88 std::cout << "entering: Open" << std::endl;
89 }
90 };
91 struct Open_Exit
92 {
93 template <class Event,class FSM,class STATE>
94 void operator()(Event const&,FSM&,STATE& )
95 {
96 std::cout << "leaving: Open" << std::endl;
97 }
98 };
99 struct Open_tag {};
100 typedef msm::front::euml::func_state<Open_tag,Open_Entry,Open_Exit> Open;
101
102 // states without entry/exit actions (can be declared as functor state, just without functors ;-) )
103 struct Stopped_tag {};
104 typedef msm::front::euml::func_state<Stopped_tag> Stopped;
105
106 struct Playing_tag {};
107 typedef msm::front::euml::func_state<Playing_tag> Playing;
108
109 // state not defining any entry or exit (declared as simple state. Equivalent)
110 struct Paused : public msm::front::state<>
111 {
112 };
113
114 // the initial state of the player SM. Must be defined
115 typedef Empty initial_state;
116
117 // transition actions
118 // as the functors are generic on events, fsm and source/target state,
119 // you can reuse them in another machine if you wish
120 struct TestFct
121 {
122 template <class EVT,class FSM,class SourceState,class TargetState>
123 void operator()(EVT const&, FSM&,SourceState& ,TargetState& )
124 {
125 cout << "transition with event:" << typeid(EVT).name() << endl;
126 }
127 };
128 struct start_playback
129 {
130 template <class EVT,class FSM,class SourceState,class TargetState>
131 void operator()(EVT const& ,FSM& ,SourceState& ,TargetState& )
132 {
133 cout << "player::start_playback" << endl;
134 }
135 };
136 struct open_drawer
137 {
138 template <class EVT,class FSM,class SourceState,class TargetState>
139 void operator()(EVT const& ,FSM& ,SourceState& ,TargetState& )
140 {
141 cout << "player::open_drawer" << endl;
142 }
143 };
144 struct close_drawer
145 {
146 template <class EVT,class FSM,class SourceState,class TargetState>
147 void operator()(EVT const& ,FSM& ,SourceState& ,TargetState& )
148 {
149 cout << "player::close_drawer" << endl;
150 }
151 };
152 struct store_cd_info
153 {
154 template <class EVT,class FSM,class SourceState,class TargetState>
155 void operator()(EVT const&,FSM& fsm ,SourceState& ,TargetState& )
156 {
157 cout << "player::store_cd_info" << endl;
158 fsm.process_event(play());
159 }
160 };
161 struct stop_playback
162 {
163 template <class EVT,class FSM,class SourceState,class TargetState>
164 void operator()(EVT const& ,FSM& ,SourceState& ,TargetState& )
165 {
166 cout << "player::stop_playback" << endl;
167 }
168 };
169 struct pause_playback
170 {
171 template <class EVT,class FSM,class SourceState,class TargetState>
172 void operator()(EVT const& ,FSM& ,SourceState& ,TargetState& )
173 {
174 cout << "player::pause_playback" << endl;
175 }
176 };
177 struct resume_playback
178 {
179 template <class EVT,class FSM,class SourceState,class TargetState>
180 void operator()(EVT const& ,FSM& ,SourceState& ,TargetState& )
181 {
182 cout << "player::resume_playback" << endl;
183 }
184 };
185 struct stop_and_open
186 {
187 template <class EVT,class FSM,class SourceState,class TargetState>
188 void operator()(EVT const& ,FSM& ,SourceState& ,TargetState& )
189 {
190 cout << "player::stop_and_open" << endl;
191 }
192 };
193 struct stopped_again
194 {
195 template <class EVT,class FSM,class SourceState,class TargetState>
196 void operator()(EVT const& ,FSM& ,SourceState& ,TargetState& )
197 {
198 cout << "player::stopped_again" << endl;
199 }
200 };
201 // guard conditions
202 struct DummyGuard
203 {
204 template <class EVT,class FSM,class SourceState,class TargetState>
205 bool operator()(EVT const& evt,FSM& fsm,SourceState& src,TargetState& tgt)
206 {
207 return true;
208 }
209 };
210 struct good_disk_format
211 {
212 template <class EVT,class FSM,class SourceState,class TargetState>
213 bool operator()(EVT const& evt ,FSM&,SourceState& ,TargetState& )
214 {
215 // to test a guard condition, let's say we understand only CDs, not DVD
216 if (evt.disc_type != DISK_CD)
217 {
218 std::cout << "wrong disk, sorry" << std::endl;
219 return false;
220 }
221 return true;
222 }
223 };
224 struct always_true
225 {
226 template <class EVT,class FSM,class SourceState,class TargetState>
227 bool operator()(EVT const& evt ,FSM&,SourceState& ,TargetState& )
228 {
229 return true;
230 }
231 };
232 // we want to define one row with the classic look.
233 bool auto_start(cd_detected const& evt)
234 {
235 return false;
236 }
237
238 typedef player_ p; // makes transition table cleaner
239
240 // Transition table for player
241 struct transition_table : mpl::vector<
242 // Start Event Next Action Guard
243 // +---------+-------------+---------+---------------------------+----------------------+
244 Row < Stopped , play , Playing , ActionSequence_
245 <mpl::vector<
246 TestFct,start_playback> >
247 , DummyGuard >,
248 Row < Stopped , open_close , Open , open_drawer , none >,
249 Row < Stopped , stop , Stopped , none , none >,
250 // +---------+-------------+---------+---------------------------+----------------------+
251 Row < Open , open_close , Empty , close_drawer , none >,
252 // +---------+-------------+---------+---------------------------+----------------------+
253 Row < Empty , open_close , Open , open_drawer , none >,
254 Row < Empty , cd_detected , Stopped , store_cd_info , And_<good_disk_format,
255 always_true> >,
256 // we here also mix with some "classical row"
257 g_row < Empty , cd_detected , Playing , &p::auto_start >,
258 // +---------+-------------+---------+---------------------------+----------------------+
259 Row < Playing , stop , Stopped , stop_playback , none >,
260 Row < Playing , pause , Paused , pause_playback , none >,
261 Row < Playing , open_close , Open , stop_and_open , none >,
262 // +---------+-------------+---------+---------------------------+----------------------+
263 Row < Paused , end_pause , Playing , resume_playback , none >,
264 Row < Paused , stop , Stopped , stop_playback , none >,
265 Row < Paused , open_close , Open , stop_and_open , none >
266 // +---------+-------------+---------+---------------------------+----------------------+
267 > {};
268 // Replaces the default no-transition response.
269 template <class FSM,class Event>
270 void no_transition(Event const& e, FSM&,int state)
271 {
272 std::cout << "no transition from state " << state
273 << " on event " << typeid(e).name() << std::endl;
274 }
275 };
276 // Pick a back-end
277 typedef msm::back::state_machine<player_> player;
278
279 //
280 // Testing utilities.
281 //
282 static char const* const state_names[] = { "Stopped", "Open", "Empty", "Playing", "Paused" };
283 void pstate(player const& p)
284 {
285 std::cout << " -> " << state_names[p.current_state()[0]] << std::endl;
286 }
287
288 void test()
289 {
290 player p;
291 // needed to start the highest-level SM. This will call on_entry and mark the start of the SM
292 p.start();
293 // go to Open, call on_exit on Empty, then action, then on_entry on Open
294 p.process_event(open_close()); pstate(p);
295 p.process_event(open_close()); pstate(p);
296 // will be rejected, wrong disk type
297 p.process_event(
298 cd_detected("louie, louie",DISK_DVD)); pstate(p);
299 p.process_event(
300 cd_detected("louie, louie",DISK_CD)); pstate(p);
301 // no need to call play() as the previous event does it in its action method
302 //p.process_event(play());
303
304 // at this point, Play is active
305 p.process_event(pause()); pstate(p);
306 // go back to Playing
307 p.process_event(end_pause()); pstate(p);
308 p.process_event(pause()); pstate(p);
309 p.process_event(stop()); pstate(p);
310 // event leading to the same state
311 // no action method called as it is not present in the transition table
312 p.process_event(stop()); pstate(p);
313 }
314 }
315
316 int main()
317 {
318 test();
319 return 0;
320 }