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