]>
Commit | Line | Data |
---|---|---|
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 <boost/statechart/event.hpp> | |
12 | #include <boost/statechart/state_machine.hpp> | |
13 | #include <boost/statechart/simple_state.hpp> | |
14 | #include <boost/statechart/transition.hpp> | |
15 | #include "boost/mpl/list.hpp" | |
16 | ||
17 | #include <vector> | |
18 | ||
19 | #include <iostream> | |
20 | #ifdef WIN32 | |
21 | #include "windows.h" | |
22 | #else | |
23 | #include <sys/time.h> | |
24 | #endif | |
25 | ||
26 | namespace sc = boost::statechart; | |
27 | namespace mpl = boost::mpl; | |
28 | ||
29 | namespace test_sc | |
30 | { | |
31 | ||
32 | //events | |
33 | struct play : sc::event< play > {}; | |
34 | struct end_pause : sc::event< end_pause > {}; | |
35 | struct stop : sc::event< stop > {}; | |
36 | struct pause : sc::event< pause > {}; | |
37 | struct open_close : sc::event< open_close > {}; | |
38 | struct cd_detected : sc::event< cd_detected > {}; | |
39 | struct NextSong: sc::event< NextSong > {}; | |
40 | struct PreviousSong : sc::event< PreviousSong >{}; | |
41 | ||
42 | struct Empty; | |
43 | struct Open; | |
44 | struct Stopped; | |
45 | struct Playing; | |
46 | struct Paused; | |
47 | // SM | |
48 | struct player : sc::state_machine< player, Empty > | |
49 | { | |
50 | void open_drawer(open_close const&) { /*std::cout << "player::open_drawer\n";*/ } | |
51 | void store_cd_info(cd_detected const& cd) {/*std::cout << "player::store_cd_info\n";*/ } | |
52 | void close_drawer(open_close const&) { /*std::cout << "player::close_drawer\n";*/ } | |
53 | void start_playback(play const&) { /*std::cout << "player::start_playback\n";*/ } | |
54 | void stopped_again(stop const&) {/*std::cout << "player::stopped_again\n";*/} | |
55 | void stop_playback(stop const&) { /*std::cout << "player::stop_playback\n";*/ } | |
56 | void pause_playback(pause const&) { /*std::cout << "player::pause_playback\n"; */} | |
57 | void stop_and_open(open_close const&) { /*std::cout << "player::stop_and_open\n";*/ } | |
58 | void resume_playback(end_pause const&) { /*std::cout << "player::resume_playback\n";*/ } | |
59 | }; | |
60 | ||
61 | struct Empty : sc::simple_state< Empty, player > | |
62 | { | |
63 | Empty() { /*std::cout << "entering Empty" << std::endl;*/ } // entry | |
64 | ~Empty() { /*std::cout << "leaving Empty" << std::endl;*/ } // exit | |
65 | typedef mpl::list< | |
66 | sc::transition< open_close, Open, | |
67 | player, &player::open_drawer >, | |
68 | sc::transition< cd_detected, Stopped, | |
69 | player, &player::store_cd_info > > reactions; | |
70 | ||
71 | }; | |
72 | struct Open : sc::simple_state< Open, player > | |
73 | { | |
74 | Open() { /*std::cout << "entering Open" << std::endl;*/ } // entry | |
75 | ~Open() { /*std::cout << "leaving Open" << std::endl;*/ } // exit | |
76 | typedef sc::transition< open_close, Empty, | |
77 | player, &player::close_drawer > reactions; | |
78 | ||
79 | }; | |
80 | struct Stopped : sc::simple_state< Stopped, player > | |
81 | { | |
82 | Stopped() { /*std::cout << "entering Stopped" << std::endl;*/ } // entry | |
83 | ~Stopped() { /*std::cout << "leaving Stopped" << std::endl;*/ } // exit | |
84 | typedef mpl::list< | |
85 | sc::transition< play, Playing, | |
86 | player, &player::start_playback >, | |
87 | sc::transition< open_close, Open, | |
88 | player, &player::open_drawer >, | |
89 | sc::transition< stop, Stopped, | |
90 | player, &player::stopped_again > > reactions; | |
91 | ||
92 | }; | |
93 | struct Song1; | |
94 | struct Playing : sc::simple_state< Playing, player,Song1 > | |
95 | { | |
96 | Playing() { /*std::cout << "entering Playing" << std::endl;*/ } // entry | |
97 | ~Playing() { /*std::cout << "leaving Playing" << std::endl;*/ } // exit | |
98 | typedef mpl::list< | |
99 | sc::transition< stop, Stopped, | |
100 | player, &player::stop_playback >, | |
101 | sc::transition< pause, Paused, | |
102 | player, &player::pause_playback >, | |
103 | sc::transition< open_close, Open, | |
104 | player, &player::stop_and_open > > reactions; | |
105 | void start_next_song(NextSong const&) { /*std::cout << "Playing::start_next_song\n";*/ } | |
106 | void start_prev_song(PreviousSong const&) { /*std::cout << "Playing::start_prev_song\n";*/ } | |
107 | }; | |
108 | struct Song2; | |
109 | struct Song1 : sc::simple_state< Song1, Playing > | |
110 | { | |
111 | Song1() { /*std::cout << "entering Song1" << std::endl;*/ } // entry | |
112 | ~Song1() { /*std::cout << "leaving Song1" << std::endl;*/ } // exit | |
113 | typedef sc::transition< NextSong, Song2, | |
114 | Playing, &Playing::start_next_song > reactions; | |
115 | }; | |
116 | struct Song3; | |
117 | struct Song2 : sc::simple_state< Song2, Playing > | |
118 | { | |
119 | Song2() { /*std::cout << "entering Song2" << std::endl;*/ } // entry | |
120 | ~Song2() { /*std::cout << "leaving Song2" << std::endl;*/ } // exit | |
121 | typedef mpl::list< | |
122 | sc::transition< NextSong, Song3, | |
123 | Playing, &Playing::start_next_song >, | |
124 | sc::transition< PreviousSong, Song1, | |
125 | Playing, &Playing::start_prev_song > > reactions; | |
126 | }; | |
127 | struct Song3 : sc::simple_state< Song3, Playing > | |
128 | { | |
129 | Song3() { /*std::cout << "entering Song3" << std::endl;*/ } // entry | |
130 | ~Song3() { /*std::cout << "leaving Song3" << std::endl;*/ } // exit | |
131 | typedef sc::transition< PreviousSong, Song2, | |
132 | Playing, &Playing::start_prev_song > reactions; | |
133 | }; | |
134 | struct Paused : sc::simple_state< Paused, player > | |
135 | { | |
136 | Paused() { /*std::cout << "entering Paused" << std::endl;*/ } // entry | |
137 | ~Paused() { /*std::cout << "leaving Paused" << std::endl;*/ } // exit | |
138 | typedef mpl::list< | |
139 | sc::transition< end_pause, Playing, | |
140 | player, &player::resume_playback >, | |
141 | sc::transition< stop, Stopped, | |
142 | player, &player::stop_playback >, | |
143 | sc::transition< open_close, Open, | |
144 | player, &player::stop_and_open > > reactions; | |
145 | }; | |
146 | } | |
147 | ||
148 | ||
149 | #ifndef WIN32 | |
150 | long mtime(struct timeval& tv1,struct timeval& tv2) | |
151 | { | |
152 | return (tv2.tv_sec-tv1.tv_sec) *1000000 + ((tv2.tv_usec-tv1.tv_usec)); | |
153 | } | |
154 | #endif | |
155 | ||
156 | int main() | |
157 | { | |
158 | test_sc::player p; | |
159 | p.initiate(); | |
160 | // for timing | |
161 | #ifdef WIN32 | |
162 | LARGE_INTEGER res; | |
163 | ::QueryPerformanceFrequency(&res); | |
164 | LARGE_INTEGER li,li2; | |
165 | ::QueryPerformanceCounter(&li); | |
166 | #else | |
167 | struct timeval tv1,tv2; | |
168 | gettimeofday(&tv1,NULL); | |
169 | #endif | |
170 | ||
171 | for (int i=0;i<100;++i) | |
172 | { | |
173 | p.process_event(test_sc::open_close()); | |
174 | p.process_event(test_sc::open_close()); | |
175 | p.process_event(test_sc::cd_detected()); | |
176 | p.process_event(test_sc::play()); | |
177 | for (int j=0;j<100;++j) | |
178 | { | |
179 | p.process_event(test_sc::NextSong()); | |
180 | p.process_event(test_sc::NextSong()); | |
181 | p.process_event(test_sc::PreviousSong()); | |
182 | p.process_event(test_sc::PreviousSong()); | |
183 | } | |
184 | ||
185 | p.process_event(test_sc::pause()); | |
186 | // go back to Playing | |
187 | p.process_event(test_sc::end_pause()); | |
188 | p.process_event(test_sc::pause()); | |
189 | p.process_event(test_sc::stop()); | |
190 | // event leading to the same state | |
191 | p.process_event(test_sc::stop()); | |
192 | p.process_event(test_sc::open_close()); | |
193 | p.process_event(test_sc::open_close()); | |
194 | } | |
195 | #ifdef WIN32 | |
196 | ::QueryPerformanceCounter(&li2); | |
197 | #else | |
198 | gettimeofday(&tv2,NULL); | |
199 | #endif | |
200 | #ifdef WIN32 | |
201 | std::cout << "sc took in s:" << (double)(li2.QuadPart-li.QuadPart)/res.QuadPart <<"\n" <<std::endl; | |
202 | #else | |
203 | std::cout << "sc took in us:" << mtime(tv1,tv2) <<"\n" <<std::endl; | |
204 | #endif | |
205 | return 0; | |
206 | } | |
207 |