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 {
open_drawertest_sc::player49 void open_drawer(open_close const&) { /*std::cout << "player::open_drawer\n";*/ }
store_cd_infotest_sc::player50 void store_cd_info(cd_detected const& cd) {/*std::cout << "player::store_cd_info\n";*/ }
close_drawertest_sc::player51 void close_drawer(open_close const&) { /*std::cout << "player::close_drawer\n";*/ }
start_playbacktest_sc::player52 void start_playback(play const&) { /*std::cout << "player::start_playback\n";*/ }
stopped_againtest_sc::player53 void stopped_again(stop const&) {/*std::cout << "player::stopped_again\n";*/}
stop_playbacktest_sc::player54 void stop_playback(stop const&) { /*std::cout << "player::stop_playback\n";*/ }
pause_playbacktest_sc::player55 void pause_playback(pause const&) { /*std::cout << "player::pause_playback\n"; */}
stop_and_opentest_sc::player56 void stop_and_open(open_close const&) { /*std::cout << "player::stop_and_open\n";*/ }
resume_playbacktest_sc::player57 void resume_playback(end_pause const&) { /*std::cout << "player::resume_playback\n";*/ }
58 };
59
60 struct Empty : sc::simple_state< Empty, player >
61 {
Emptytest_sc::Empty62 Empty() { /*std::cout << "entering Empty" << std::endl;*/ } // entry
~Emptytest_sc::Empty63 ~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 {
Opentest_sc::Open73 Open() { /*std::cout << "entering Open" << std::endl;*/ } // entry
~Opentest_sc::Open74 ~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 {
Stoppedtest_sc::Stopped81 Stopped() { /*std::cout << "entering Stopped" << std::endl;*/ } // entry
~Stoppedtest_sc::Stopped82 ~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 {
Playingtest_sc::Playing94 Playing() { /*std::cout << "entering Playing" << std::endl;*/ } // entry
~Playingtest_sc::Playing95 ~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 {
Pausedtest_sc::Paused106 Paused() { /*std::cout << "entering Paused" << std::endl;*/ } // entry
~Pausedtest_sc::Paused107 ~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
mtime(struct timeval & tv1,struct timeval & tv2)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
main()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
170