]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/msm/doc/HTML/examples/ExampleCircularBuffer.cpp
4 #include <boost/msm/back/state_machine.hpp>
5 // header for support of circular_buffer
6 #include <boost/msm/back/queue_container_circular.hpp>
8 #include <boost/msm/front/state_machine_def.hpp>
10 #include <boost/msm/front/functor_row.hpp>
11 #include <boost/msm/front/euml/common.hpp>
13 #include <boost/msm/front/euml/operator.hpp>
16 namespace msm
= boost::msm
;
17 namespace mpl
= boost::mpl
;
18 using namespace msm::front
;
20 using namespace msm::front::euml
;
22 namespace // Concrete FSM implementation
31 // A "complicated" event type that carries some data.
39 cd_detected(std::string name
, DiskTypeEnum diskType
)
45 DiskTypeEnum disc_type
;
48 // front-end: define the FSM structure
49 struct player_
: public msm::front::state_machine_def
<player_
>
51 // The list of FSM states
52 struct Empty
: public msm::front::state
<>
54 // every (optional) entry/exit methods get the event passed.
55 template <class Event
,class FSM
>
56 void on_entry(Event
const&,FSM
& ) {std::cout
<< "entering: Empty" << std::endl
;}
57 template <class Event
,class FSM
>
58 void on_exit(Event
const&,FSM
& ) {std::cout
<< "leaving: Empty" << std::endl
;}
60 struct Open
: public msm::front::state
<>
62 template <class Event
,class FSM
>
63 void on_entry(Event
const& ,FSM
&) {std::cout
<< "entering: Open" << std::endl
;}
64 template <class Event
,class FSM
>
65 void on_exit(Event
const&,FSM
& ) {std::cout
<< "leaving: Open" << std::endl
;}
68 struct Stopped
: public msm::front::state
<>
70 // when stopped, the CD is loaded
71 template <class Event
,class FSM
>
72 void on_entry(Event
const& ,FSM
&) {std::cout
<< "entering: Stopped" << std::endl
;}
73 template <class Event
,class FSM
>
74 void on_exit(Event
const&,FSM
& ) {std::cout
<< "leaving: Stopped" << std::endl
;}
77 struct Playing
: public msm::front::state
<>
79 template <class Event
,class FSM
>
80 void on_entry(Event
const&,FSM
& ) {std::cout
<< "entering: Playing" << std::endl
;}
81 template <class Event
,class FSM
>
82 void on_exit(Event
const&,FSM
& ) {std::cout
<< "leaving: Playing" << std::endl
;}
85 // state not defining any entry or exit
86 struct Paused
: public msm::front::state
<>
90 // the initial state of the player SM. Must be defined
91 typedef Empty initial_state
;
94 // as the functors are generic on events, fsm and source/target state,
95 // you can reuse them in another machine if you wish
98 template <class EVT
,class FSM
,class SourceState
,class TargetState
>
99 void operator()(EVT
const&, FSM
&,SourceState
& ,TargetState
& )
101 cout
<< "transition with event:" << typeid(EVT
).name() << endl
;
104 struct start_playback
106 template <class EVT
,class FSM
,class SourceState
,class TargetState
>
107 void operator()(EVT
const& ,FSM
& ,SourceState
& ,TargetState
& )
109 cout
<< "player::start_playback" << endl
;
114 template <class EVT
,class FSM
,class SourceState
,class TargetState
>
115 void operator()(EVT
const& ,FSM
& ,SourceState
& ,TargetState
& )
117 cout
<< "player::open_drawer" << endl
;
122 template <class EVT
,class FSM
,class SourceState
,class TargetState
>
123 void operator()(EVT
const& ,FSM
& ,SourceState
& ,TargetState
& )
125 cout
<< "player::close_drawer" << endl
;
130 template <class EVT
,class FSM
,class SourceState
,class TargetState
>
131 void operator()(EVT
const&,FSM
& fsm
,SourceState
& ,TargetState
& )
133 cout
<< "player::store_cd_info" << endl
;
134 fsm
.process_event(play());
139 template <class EVT
,class FSM
,class SourceState
,class TargetState
>
140 void operator()(EVT
const& ,FSM
& ,SourceState
& ,TargetState
& )
142 cout
<< "player::stop_playback" << endl
;
145 struct pause_playback
147 template <class EVT
,class FSM
,class SourceState
,class TargetState
>
148 void operator()(EVT
const& ,FSM
& ,SourceState
& ,TargetState
& )
150 cout
<< "player::pause_playback" << endl
;
153 struct resume_playback
155 template <class EVT
,class FSM
,class SourceState
,class TargetState
>
156 void operator()(EVT
const& ,FSM
& ,SourceState
& ,TargetState
& )
158 cout
<< "player::resume_playback" << endl
;
163 template <class EVT
,class FSM
,class SourceState
,class TargetState
>
164 void operator()(EVT
const& ,FSM
& ,SourceState
& ,TargetState
& )
166 cout
<< "player::stop_and_open" << endl
;
171 template <class EVT
,class FSM
,class SourceState
,class TargetState
>
172 void operator()(EVT
const& ,FSM
& ,SourceState
& ,TargetState
& )
174 cout
<< "player::stopped_again" << endl
;
180 template <class EVT
,class FSM
,class SourceState
,class TargetState
>
181 bool operator()(EVT
const& evt
,FSM
& fsm
,SourceState
& src
,TargetState
& tgt
)
186 struct good_disk_format
188 template <class EVT
,class FSM
,class SourceState
,class TargetState
>
189 bool operator()(EVT
const& evt
,FSM
&,SourceState
& ,TargetState
& )
191 // to test a guard condition, let's say we understand only CDs, not DVD
192 if (evt
.disc_type
!= DISK_CD
)
194 std::cout
<< "wrong disk, sorry" << std::endl
;
202 template <class EVT
,class FSM
,class SourceState
,class TargetState
>
203 bool operator()(EVT
const& evt
,FSM
&,SourceState
& ,TargetState
& )
208 // we want to define one row with the classic look.
209 bool auto_start(cd_detected
const& evt
)
214 typedef player_ p
; // makes transition table cleaner
216 // Transition table for player
217 struct transition_table
: mpl::vector
<
218 // Start Event Next Action Guard
219 // +---------+-------------+---------+---------------------------+----------------------+
220 Row
< Stopped
, play
, Playing
, ActionSequence_
222 TestFct
,start_playback
> >
224 Row
< Stopped
, open_close
, Open
, open_drawer
, none
>,
225 Row
< Stopped
, stop
, Stopped
, none
, none
>,
226 // +---------+-------------+---------+---------------------------+----------------------+
227 Row
< Open
, open_close
, Empty
, close_drawer
, none
>,
228 // +---------+-------------+---------+---------------------------+----------------------+
229 Row
< Empty
, open_close
, Open
, open_drawer
, none
>,
230 Row
< Empty
, cd_detected
, Stopped
, store_cd_info
, And_
<good_disk_format
,
232 // we here also mix with some "classical row"
233 g_row
< Empty
, cd_detected
, Playing
, &p::auto_start
>,
234 // +---------+-------------+---------+---------------------------+----------------------+
235 Row
< Playing
, stop
, Stopped
, stop_playback
, none
>,
236 Row
< Playing
, pause
, Paused
, pause_playback
, none
>,
237 Row
< Playing
, open_close
, Open
, stop_and_open
, none
>,
238 // +---------+-------------+---------+---------------------------+----------------------+
239 Row
< Paused
, end_pause
, Playing
, resume_playback
, none
>,
240 Row
< Paused
, stop
, Stopped
, stop_playback
, none
>,
241 Row
< Paused
, open_close
, Open
, stop_and_open
, none
>
242 // +---------+-------------+---------+---------------------------+----------------------+
244 // Replaces the default no-transition response.
245 template <class FSM
,class Event
>
246 void no_transition(Event
const& e
, FSM
&,int state
)
248 std::cout
<< "no transition from state " << state
249 << " on event " << typeid(e
).name() << std::endl
;
253 typedef msm::back::state_machine
<player_
, msm::back::queue_container_circular
> player
;
256 // Testing utilities.
258 static char const* const state_names
[] = { "Stopped", "Open", "Empty", "Playing", "Paused" };
259 void pstate(player
const& p
)
261 std::cout
<< " -> " << state_names
[p
.current_state()[0]] << std::endl
;
267 // we get the message queue and limit it to capacity 1
268 // get_message_queue returns the queue container (in this case circular_buffer)
269 p
.get_message_queue().set_capacity(1);
270 // needed to start the highest-level SM. This will call on_entry and mark the start of the SM
272 // go to Open, call on_exit on Empty, then action, then on_entry on Open
273 p
.process_event(open_close()); pstate(p
);
274 p
.process_event(open_close()); pstate(p
);
275 // will be rejected, wrong disk type
277 cd_detected("louie, louie",DISK_DVD
)); pstate(p
);
279 cd_detected("louie, louie",DISK_CD
)); pstate(p
);
280 // no need to call play() as the previous event does it in its action method
281 //p.process_event(play());
283 // at this point, Play is active
284 p
.process_event(pause()); pstate(p
);
285 // go back to Playing
286 p
.process_event(end_pause()); pstate(p
);
287 p
.process_event(pause()); pstate(p
);
288 p
.process_event(stop()); pstate(p
);
289 // event leading to the same state
290 // no action method called as it is not present in the transition table
291 p
.process_event(stop()); pstate(p
);