]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/msm/doc/HTML/examples/iPod_distributed/iPod.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)
15 #define FUSION_MAX_VECTOR_SIZE 20
17 #include "boost/mpl/vector/vector50.hpp"
18 #include <boost/msm/back/state_machine.hpp>
19 #include <boost/msm/front/state_machine_def.hpp>
22 #include "PlayingMode.hpp"
23 #include "MenuMode.hpp"
26 namespace msm
= boost::msm
;
28 namespace // Concrete FSM implementation
31 typedef msm::back::state_machine
<iPod_
,
32 ::boost::msm::back::favor_compile_time
> iPod
;
34 // Concrete FSM implementation
35 struct iPod_
: public msm::front::state_machine_def
<iPod_
>
37 // The list of FSM states
38 struct NotHolding
: public msm::front::state
<>
40 template <class Event
,class FSM
>
41 void on_entry(Event
const&,FSM
& ) {std::cout
<< "starting: NotHolding" << std::endl
;}
42 template <class Event
,class FSM
>
43 void on_exit(Event
const&,FSM
& ) {std::cout
<< "finishing: NotHolding" << std::endl
;}
45 struct Holding
: public msm::front::interrupt_state
<NoHold
>
47 template <class Event
,class FSM
>
48 void on_entry(Event
const&,FSM
& ) {std::cout
<< "starting: Holding" << std::endl
;}
49 template <class Event
,class FSM
>
50 void on_exit(Event
const&,FSM
& ) {std::cout
<< "finishing: Holding" << std::endl
;}
52 struct NotPlaying
: public msm::front::state
<>
54 template <class Event
,class FSM
>
55 void on_entry(Event
const&,FSM
& ) {std::cout
<< "starting: NotPlaying" << std::endl
;}
56 template <class Event
,class FSM
>
57 void on_exit(Event
const&,FSM
& ) {std::cout
<< "finishing: NotPlaying" << std::endl
;}
59 struct NoMenuMode
: public msm::front::state
<>
61 template <class Event
,class FSM
>
62 void on_entry(Event
const&,FSM
& ) {std::cout
<< "starting: NoMenuMode" << std::endl
;}
63 template <class Event
,class FSM
>
64 void on_exit(Event
const&,FSM
& ) {std::cout
<< "finishing: NoMenuMode" << std::endl
;}
66 struct NoOnOffButton
: public msm::front::state
<>
68 template <class Event
,class FSM
>
69 void on_entry(Event
const&,FSM
& ) {std::cout
<< "starting: NoOnOffButton" << std::endl
;}
70 template <class Event
,class FSM
>
71 void on_exit(Event
const&,FSM
& ) {std::cout
<< "finishing: NoOnOffButton" << std::endl
;}
73 struct OffDown
: public msm::front::state
<>
75 template <class Event
,class FSM
>
76 void on_entry(Event
const&,FSM
& ) {std::cout
<< "starting: OffDown, start timer" << std::endl
;}
77 template <class Event
,class FSM
>
78 void on_exit(Event
const&,FSM
& ) {std::cout
<< "finishing: OffDown, end timer" << std::endl
;}
80 struct PlayerOff
: public msm::front::state
<>
82 template <class Event
,class FSM
>
83 void on_entry(Event
const&,FSM
& ) {std::cout
<< "starting: PlayerOff" << std::endl
;}
84 template <class Event
,class FSM
>
85 void on_exit(Event
const&,FSM
& ) {std::cout
<< "finishing: PlayerOff" << std::endl
;}
87 struct CheckMiddleButton
: public msm::front::state
<>
89 template <class Event
,class FSM
>
90 void on_entry(Event
const&,FSM
& ) {std::cout
<< "starting: CheckMiddleButton" << std::endl
;}
91 template <class Event
,class FSM
>
92 void on_exit(Event
const&,FSM
& ) {std::cout
<< "finishing: CheckMiddleButton" << std::endl
;}
95 // the initial state of the player SM. Must be defined
96 typedef mpl::vector5
<NotHolding
,NotPlaying
,NoMenuMode
,NoOnOffButton
,CheckMiddleButton
>
99 void send_ActivateMenu(EndPlay
const&)
101 std::cout
<< "leaving Playing" << std::endl
;
102 // we need to activate the menu and simulate its button
103 (static_cast<iPod
*>(this))->process_event(MenuButton());
105 void send_StartSong(CloseMenu
const&)
107 // we suppose the 5th song was selected
108 (static_cast<iPod
*>(this))->process_event(StartSong(5));
110 void send_PlayPause(SouthReleased
const&)
112 // action using the message queue to generate another event
113 (static_cast<iPod
*>(this))->process_event(PlayPause());
115 void send_Off(OnOffTimer
const&)
117 std::cout
<< "turning player off" << std::endl
;
118 (static_cast<iPod
*>(this))->process_event(Off());
120 void send_PlayingMiddleButton(MiddleButton
const&)
122 (static_cast<iPod
*>(this))->process_event(PlayingMiddleButton());
124 void send_MenuMiddleButton(MiddleButton
const&)
126 (static_cast<iPod
*>(this))->process_event(MenuMiddleButton());
129 bool is_menu(MiddleButton
const&)
131 return (static_cast<iPod
*>(this))->is_flag_active
<MenuActive
>();
133 bool is_no_menu(MiddleButton
const& evt
)
135 return !is_menu(evt
);
137 template <class EVENT
>
138 void switch_on(EVENT
const&)
140 std::cout
<< "turning player on" << std::endl
;
142 typedef iPod_ fsm
; // makes transition table cleaner
144 // Transition table for player
145 struct transition_table
: mpl::vector
<
146 // Start Event Next Action Guard
147 // +-------------------+---------------+-------------------+--------------------------------+----------------------+
148 _row
< NotHolding
, Hold
, Holding
>,
149 _row
< Holding
, NoHold
, NotHolding
>,
150 // +-------------------+---------------+-------------------+--------------------------------+----------------------+
151 _row
< NotPlaying
, PlayPause
, PlayingMode
>,
152 a_row
< PlayingMode::exit_pt
<PlayingMode_::
153 PlayingExit
> , EndPlay
, NotPlaying
, &fsm::send_ActivateMenu
>,
154 // +-------------------+---------------+-------------------+--------------------------------+----------------------+
155 _row
< NoMenuMode
, MenuButton
, MenuMode
>,
156 a_row
< MenuMode::exit_pt
<MenuMode_::
157 MenuExit
> , CloseMenu
, NoMenuMode
, &fsm::send_StartSong
>,
158 // +-------------------+---------------+-------------------+--------------------------------+----------------------+
159 _row
< NoOnOffButton
, SouthPressed
, OffDown
>,
160 a_row
< OffDown
, SouthReleased
, NoOnOffButton
, &fsm::send_PlayPause
>,
161 a_row
< OffDown
, OnOffTimer
, PlayerOff
, &fsm::send_Off
>,
162 a_row
< PlayerOff
, SouthPressed
, NoOnOffButton
, &fsm::switch_on
>,
163 a_row
< PlayerOff
, NoHold
, NoOnOffButton
, &fsm::switch_on
>,
164 // +-------------------+---------------+--------------------+--------------------------------+----------------------+
165 row
< CheckMiddleButton
, MiddleButton
, CheckMiddleButton
, &fsm::send_PlayingMiddleButton
, &fsm::is_menu
>,
166 row
< CheckMiddleButton
, MiddleButton
, CheckMiddleButton
, &fsm::send_MenuMiddleButton
, &fsm::is_no_menu
>
167 // +-------------------+---------------+--------------------+--------------------------------+----------------------+
170 // Replaces the default no-transition response.
171 template <class FSM
,class Event
>
172 void no_transition(Event
const& e
, FSM
&,int state
)
174 std::cout
<< "no transition from state " << state
175 << " on event " << typeid(e
).name() << std::endl
;
183 // we first press Hold
184 std::cout
<< "pressing hold" << std::endl
;
185 sm
.process_event(Hold());
186 // pressing a button is now ignored
187 std::cout
<< "pressing a button" << std::endl
;
188 sm
.process_event(SouthPressed());
189 // or even one contained in a submachine
190 sm
.process_event(EastPressed());
192 std::cout
<< "no more holding, end interrupt event sent" << std::endl
;
193 sm
.process_event(NoHold());
194 std::cout
<< "pressing South button a short time" << std::endl
;
195 sm
.process_event(SouthPressed());
196 // we suppose a short pressing leading to playing a song
197 sm
.process_event(SouthReleased());
198 // we move to the next song
199 std::cout
<< "we move to the next song" << std::endl
;
200 sm
.process_event(NextSong());
201 // then back to no song => exit from playing, menu active
202 std::cout
<< "we press twice the West button (simulated)=> end of playing" << std::endl
;
203 sm
.process_event(PreviousSong());
204 sm
.process_event(PreviousSong());
205 // even in menu mode, pressing play will start playing the first song
206 std::cout
<< "pressing play/pause" << std::endl
;
207 sm
.process_event(SouthPressed());
208 sm
.process_event(SouthReleased());
209 // of course pausing must be possible
210 std::cout
<< "pressing play/pause" << std::endl
;
211 sm
.process_event(SouthPressed());
212 sm
.process_event(SouthReleased());
213 std::cout
<< "pressing play/pause" << std::endl
;
214 sm
.process_event(SouthPressed());
215 sm
.process_event(SouthReleased());
216 // while playing, you can fast forward
217 std::cout
<< "pressing East button a long time" << std::endl
;
218 sm
.process_event(EastPressed());
219 // let's suppose the timer just fired
220 sm
.process_event(ForwardTimer());
221 sm
.process_event(ForwardTimer());
222 // end of fast forwarding
223 std::cout
<< "releasing East button" << std::endl
;
224 sm
.process_event(EastReleased());
225 // we now press the middle button to set playing at a given position
226 std::cout
<< "pressing Middle button, fast forwarding disabled" << std::endl
;
227 sm
.process_event(MiddleButton());
228 std::cout
<<"pressing East button to fast forward" << std::endl
;
229 sm
.process_event(EastPressed());
230 // we switch off and on
231 std::cout
<<"switch off player" << std::endl
;
232 sm
.process_event(SouthPressed());
233 sm
.process_event(OnOffTimer());
234 std::cout
<<"switch on player" << std::endl
;
235 sm
.process_event(SouthPressed());