]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/msm/doc/PDF/examples/Constructor.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)
13 #include <boost/msm/back/state_machine.hpp>
15 #include <boost/msm/front/state_machine_def.hpp>
17 namespace msm
= boost::msm
;
18 namespace mpl
= boost::mpl
;
20 struct SomeExternalContext
22 SomeExternalContext(int b
):bla(b
){}
35 struct PreviousSong
{};
37 // A "complicated" event type that carries some data.
45 cd_detected(std::string name
, DiskTypeEnum diskType
)
51 DiskTypeEnum disc_type
;
54 // front-end: define the FSM structure
55 struct player_
: public msm::front::state_machine_def
<player_
>
57 player_(SomeExternalContext
& context
,int someint
)
60 std::cout
<< "context value:" << context_
.bla
<< " with value:" << someint
<< std::endl
;
64 SomeExternalContext
& context_
;
66 // The list of FSM states
67 struct Empty
: public msm::front::state
<>
71 Empty(int i
):data_(i
){}
72 // every (optional) entry/exit methods get the event passed.
73 template <class Event
,class FSM
>
74 void on_entry(Event
const&,FSM
& ) {std::cout
<< "entering: Empty" << std::endl
;}
75 template <class Event
,class FSM
>
76 void on_exit(Event
const&,FSM
& ) {std::cout
<< "leaving: Empty" << std::endl
;}
78 struct Open
: public msm::front::state
<>
82 Open(int i
):data_(i
){}
84 template <class Event
,class FSM
>
85 void on_entry(Event
const& ,FSM
&) {std::cout
<< "entering: Open" << std::endl
;}
86 template <class Event
,class FSM
>
87 void on_exit(Event
const&,FSM
& ) {std::cout
<< "leaving: Open" << std::endl
;}
90 // sm_ptr still supported but deprecated as functors are a much better way to do the same thing
91 struct Stopped
: public msm::front::state
<msm::front::default_base_state
,msm::front::sm_ptr
>
93 template <class Event
,class FSM
>
94 void on_entry(Event
const& ,FSM
&) {std::cout
<< "entering: Stopped" << std::endl
;}
95 template <class Event
,class FSM
>
96 void on_exit(Event
const&,FSM
& ) {std::cout
<< "leaving: Stopped" << std::endl
;}
97 void set_sm_ptr(player_
* pl
)
104 struct Playing_
: public msm::front::state_machine_def
<Playing_
>
106 // when playing, the CD is loaded and we are in either pause or playing (duh)
107 template <class Event
,class FSM
>
108 void on_entry(Event
const&,FSM
& ) {std::cout
<< "entering: Playing" << std::endl
;}
109 template <class Event
,class FSM
>
110 void on_exit(Event
const&,FSM
& ) {std::cout
<< "leaving: Playing" << std::endl
;}
112 // The list of FSM states
113 struct Song1
: public msm::front::state
<>
117 Song1(int i
):data_(i
){}
119 template <class Event
,class FSM
>
120 void on_entry(Event
const&,FSM
& ) {std::cout
<< "starting: First song" << std::endl
;}
121 template <class Event
,class FSM
>
122 void on_exit(Event
const&,FSM
& ) {std::cout
<< "finishing: First Song" << std::endl
;}
125 struct Song2
: public msm::front::state
<>
127 template <class Event
,class FSM
>
128 void on_entry(Event
const&,FSM
& ) {std::cout
<< "starting: Second song" << std::endl
;}
129 template <class Event
,class FSM
>
130 void on_exit(Event
const&,FSM
& ) {std::cout
<< "finishing: Second Song" << std::endl
;}
132 struct Song3
: public msm::front::state
<>
134 template <class Event
,class FSM
>
135 void on_entry(Event
const&,FSM
& ) {std::cout
<< "starting: Third song" << std::endl
;}
136 template <class Event
,class FSM
>
137 void on_exit(Event
const&,FSM
& ) {std::cout
<< "finishing: Third Song" << std::endl
;}
139 // the initial state. Must be defined
140 typedef Song1 initial_state
;
141 // transition actions
142 void start_next_song(NextSong
const&) { std::cout
<< "Playing::start_next_song\n"; }
143 void start_prev_song(PreviousSong
const&) { std::cout
<< "Playing::start_prev_song\n"; }
146 typedef Playing_ pl
; // makes transition table cleaner
147 // Transition table for Playing
148 struct transition_table
: mpl::vector4
<
149 // Start Event Next Action Guard
150 // +---------+-------------+---------+---------------------+----------------------+
151 a_row
< Song1
, NextSong
, Song2
, &pl::start_next_song
>,
152 a_row
< Song2
, PreviousSong
, Song1
, &pl::start_prev_song
>,
153 a_row
< Song2
, NextSong
, Song3
, &pl::start_next_song
>,
154 a_row
< Song3
, PreviousSong
, Song2
, &pl::start_prev_song
>
155 // +---------+-------------+---------+---------------------+----------------------+
157 // Replaces the default no-transition response.
158 template <class FSM
,class Event
>
159 void no_transition(Event
const& e
, FSM
&,int state
)
161 std::cout
<< "no transition from state " << state
162 << " on event " << typeid(e
).name() << std::endl
;
166 typedef msm::back::state_machine
<Playing_
> Playing
;
168 // state not defining any entry or exit
169 struct Paused
: public msm::front::state
<>
173 // the initial state of the player SM. Must be defined
174 typedef Empty initial_state
;
176 // transition actions
177 void start_playback(play
const&) { std::cout
<< "player::start_playback\n"; }
178 void open_drawer(open_close
const&) { std::cout
<< "player::open_drawer\n"; }
179 void close_drawer(open_close
const&) { std::cout
<< "player::close_drawer\n"; }
180 void store_cd_info(cd_detected
const&) { std::cout
<< "player::store_cd_info\n"; }
181 void stop_playback(stop
const&) { std::cout
<< "player::stop_playback\n"; }
182 void pause_playback(pause
const&) { std::cout
<< "player::pause_playback\n"; }
183 void resume_playback(end_pause
const&) { std::cout
<< "player::resume_playback\n"; }
184 void stop_and_open(open_close
const&) { std::cout
<< "player::stop_and_open\n"; }
185 void stopped_again(stop
const&) {std::cout
<< "player::stopped_again\n";}
187 bool good_disk_format(cd_detected
const& evt
)
189 // to test a guard condition, let's say we understand only CDs, not DVD
190 if (evt
.disc_type
!= DISK_CD
)
192 std::cout
<< "wrong disk, sorry" << std::endl
;
197 // used to show a transition conflict. This guard will simply deactivate one transition and thus
198 // solve the conflict
199 bool auto_start(cd_detected
const&)
204 typedef player_ p
; // makes transition table cleaner
206 // Transition table for player
207 struct transition_table
: mpl::vector
<
208 // Start Event Next Action Guard
209 // +---------+-------------+---------+---------------------+----------------------+
210 a_row
< Stopped
, play
, Playing
, &p::start_playback
>,
211 a_row
< Stopped
, open_close
, Open
, &p::open_drawer
>,
212 _row
< Stopped
, stop
, Stopped
>,
213 // +---------+-------------+---------+---------------------+----------------------+
214 a_row
< Open
, open_close
, Empty
, &p::close_drawer
>,
215 // +---------+-------------+---------+---------------------+----------------------+
216 a_row
< Empty
, open_close
, Open
, &p::open_drawer
>,
217 row
< Empty
, cd_detected
, Stopped
, &p::store_cd_info
,&p::good_disk_format
>,
218 row
< Empty
, cd_detected
, Playing
, &p::store_cd_info
,&p::auto_start
>,
219 // +---------+-------------+---------+---------------------+----------------------+
220 a_row
< Playing
, stop
, Stopped
, &p::stop_playback
>,
221 a_row
< Playing
, pause
, Paused
, &p::pause_playback
>,
222 a_row
< Playing
, open_close
, Open
, &p::stop_and_open
>,
223 // +---------+-------------+---------+---------------------+----------------------+
224 a_row
< Paused
, end_pause
, Playing
, &p::resume_playback
>,
225 a_row
< Paused
, stop
, Stopped
, &p::stop_playback
>,
226 a_row
< Paused
, open_close
, Open
, &p::stop_and_open
>
227 // +---------+-------------+---------+---------------------+----------------------+
229 // Replaces the default no-transition response.
230 template <class FSM
,class Event
>
231 void no_transition(Event
const& e
, FSM
&,int state
)
233 std::cout
<< "no transition from state " << state
234 << " on event " << typeid(e
).name() << std::endl
;
238 typedef msm::back::state_machine
<player_
> player
;
241 // Testing utilities.
243 static char const* const state_names
[] = { "Stopped", "Open", "Empty", "Playing", "Paused" };
244 void pstate(player
const& p
)
246 std::cout
<< " -> " << state_names
[p
.current_state()[0]] << std::endl
;
251 SomeExternalContext
ctx(3);
253 // create a player with an argument by reference and an int
254 // (go to the constructor front-end)
255 player
p1(boost::ref(ctx
),5);
258 // create a player with a copy of an Empty state, an argument by reference and an int
259 // (last 2 go to the constructor front-end)
260 player
p2(msm::back::states_
<< player_::Empty(1),boost::ref(ctx
),5);
261 std::cout
<< "Empty's data should be 1. Is: " << p2
.get_state
<player_::Empty
&>().data_
<< std::endl
;
263 std::cout
<< "Set a new Empty state" << std::endl
;
264 p2
.set_states(msm::back::states_
<< player_::Empty(5));
265 std::cout
<< "Empty's data should be 5. Is: " << p2
.get_state
<player_::Empty
&>().data_
<< std::endl
;
267 std::cout
<< "Set new Empty and Open states" << std::endl
;
268 p2
.set_states(msm::back::states_
<< player_::Empty(7) << player_::Open(2));
269 std::cout
<< "Empty's data should be 7. Is: " << p2
.get_state
<player_::Empty
&>().data_
<< std::endl
;
270 std::cout
<< "Open's data should be 2. Is: " << p2
.get_state
<player_::Open
&>().data_
<< std::endl
;
273 // create a player with a copy of an Empty state, a copy of a Playing submachine
274 // (which is itself created by a copy of Song1)
275 // an argument by reference and an int
276 // (last 2 go to the constructor front-end)
277 player
p(msm::back::states_
<< player_::Empty(1)
278 << player_::Playing(msm::back::states_
<< player_::Playing_::Song1(8)),
281 std::cout
<< "Song1's data should be 8. Is: "
282 << p
.get_state
<player_::Playing
&>().get_state
<player_::Playing_::Song1
&>().data_
<< std::endl
;