]>
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 | ||
40 | ||
41 | struct Empty; | |
42 | struct Open; | |
43 | struct Stopped; | |
44 | struct Playing; | |
45 | struct Paused; | |
46 | // SM | |
47 | struct player : sc::state_machine< player, Empty > | |
48 | { | |
49 | void open_drawer(open_close const&) { /*std::cout << "player::open_drawer\n";*/ } | |
50 | void store_cd_info(cd_detected const& cd) {/*std::cout << "player::store_cd_info\n";*/ } | |
51 | void close_drawer(open_close const&) { /*std::cout << "player::close_drawer\n";*/ } | |
52 | void start_playback(play const&) { /*std::cout << "player::start_playback\n";*/ } | |
53 | void stopped_again(stop const&) {/*std::cout << "player::stopped_again\n";*/} | |
54 | void stop_playback(stop const&) { /*std::cout << "player::stop_playback\n";*/ } | |
55 | void pause_playback(pause const&) { /*std::cout << "player::pause_playback\n"; */} | |
56 | void stop_and_open(open_close const&) { /*std::cout << "player::stop_and_open\n";*/ } | |
57 | void resume_playback(end_pause const&) { /*std::cout << "player::resume_playback\n";*/ } | |
58 | }; | |
59 | ||
60 | struct Empty : sc::simple_state< Empty, player > | |
61 | { | |
62 | Empty() { /*std::cout << "entering Empty" << std::endl;*/ } // entry | |
63 | ~Empty() { /*std::cout << "leaving Empty" << std::endl;*/ } // exit | |
64 | typedef mpl::list< | |
65 | sc::transition< open_close, Open, | |
66 | player, &player::open_drawer >, | |
67 | sc::transition< cd_detected, Stopped, | |
68 | player, &player::store_cd_info > > reactions; | |
69 | ||
70 | }; | |
71 | struct Open : sc::simple_state< Open, player > | |
72 | { | |
73 | Open() { /*std::cout << "entering Open" << std::endl;*/ } // entry | |
74 | ~Open() { /*std::cout << "leaving Open" << std::endl;*/ } // exit | |
75 | typedef sc::transition< open_close, Empty, | |
76 | player, &player::close_drawer > reactions; | |
77 | ||
78 | }; | |
79 | struct Stopped : sc::simple_state< Stopped, player > | |
80 | { | |
81 | Stopped() { /*std::cout << "entering Stopped" << std::endl;*/ } // entry | |
82 | ~Stopped() { /*std::cout << "leaving Stopped" << std::endl;*/ } // exit | |
83 | typedef mpl::list< | |
84 | sc::transition< play, Playing, | |
85 | player, &player::start_playback >, | |
86 | sc::transition< open_close, Open, | |
87 | player, &player::open_drawer >, | |
88 | sc::transition< stop, Stopped, | |
89 | player, &player::stopped_again > > reactions; | |
90 | ||
91 | }; | |
92 | struct Playing : sc::simple_state< Playing, player > | |
93 | { | |
94 | Playing() { /*std::cout << "entering Playing" << std::endl;*/ } // entry | |
95 | ~Playing() { /*std::cout << "leaving Playing" << std::endl;*/ } // exit | |
96 | typedef mpl::list< | |
97 | sc::transition< stop, Stopped, | |
98 | player, &player::stop_playback >, | |
99 | sc::transition< pause, Paused, | |
100 | player, &player::pause_playback >, | |
101 | sc::transition< open_close, Open, | |
102 | player, &player::stop_and_open > > reactions; | |
103 | }; | |
104 | struct Paused : sc::simple_state< Paused, player > | |
105 | { | |
106 | Paused() { /*std::cout << "entering Paused" << std::endl;*/ } // entry | |
107 | ~Paused() { /*std::cout << "leaving Paused" << std::endl;*/ } // exit | |
108 | typedef mpl::list< | |
109 | sc::transition< end_pause, Playing, | |
110 | player, &player::resume_playback >, | |
111 | sc::transition< stop, Stopped, | |
112 | player, &player::stop_playback >, | |
113 | sc::transition< open_close, Open, | |
114 | player, &player::stop_and_open > > reactions; | |
115 | }; | |
116 | } | |
117 | ||
118 | ||
119 | #ifndef WIN32 | |
120 | long mtime(struct timeval& tv1,struct timeval& tv2) | |
121 | { | |
122 | return (tv2.tv_sec-tv1.tv_sec) *1000000 + ((tv2.tv_usec-tv1.tv_usec)); | |
123 | } | |
124 | #endif | |
125 | ||
126 | ||
127 | int main() | |
128 | { | |
129 | test_sc::player p; | |
130 | p.initiate(); | |
131 | // for timing | |
132 | #ifdef WIN32 | |
133 | LARGE_INTEGER res; | |
134 | ::QueryPerformanceFrequency(&res); | |
135 | LARGE_INTEGER li,li2; | |
136 | ::QueryPerformanceCounter(&li); | |
137 | #else | |
138 | struct timeval tv1,tv2; | |
139 | gettimeofday(&tv1,NULL); | |
140 | #endif | |
141 | for (int i=0;i<100;++i) | |
142 | { | |
143 | p.process_event(test_sc::open_close()); | |
144 | p.process_event(test_sc::open_close()); | |
145 | p.process_event(test_sc::cd_detected()); | |
146 | p.process_event(test_sc::play()); | |
147 | p.process_event(test_sc::pause()); | |
148 | // go back to Playing | |
149 | p.process_event(test_sc::end_pause()); | |
150 | p.process_event(test_sc::pause()); | |
151 | p.process_event(test_sc::stop()); | |
152 | // event leading to the same state | |
153 | p.process_event(test_sc::stop()); | |
154 | p.process_event(test_sc::open_close()); | |
155 | p.process_event(test_sc::open_close()); | |
156 | } | |
157 | #ifdef WIN32 | |
158 | ::QueryPerformanceCounter(&li2); | |
159 | #else | |
160 | gettimeofday(&tv2,NULL); | |
161 | #endif | |
162 | #ifdef WIN32 | |
163 | std::cout << "sc took in s:" << (double)(li2.QuadPart-li.QuadPart)/res.QuadPart <<"\n" <<std::endl; | |
164 | #else | |
165 | std::cout << "sc took in us:" << mtime(tv1,tv2) <<"\n" <<std::endl; | |
166 | #endif | |
167 | return 0; | |
168 | } | |
169 |