]>
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 "stdafx.h" | |
12 | ||
13 | #include <boost/msm/back/state_machine.hpp> | |
14 | #include <boost/msm/front/state_machine_def.hpp> | |
15 | #include <boost/msm/front/euml/euml.hpp> | |
16 | #include <boost/msm/front/euml/stl.hpp> | |
17 | ||
18 | namespace msm = boost::msm; | |
19 | namespace mpl = boost::mpl; | |
20 | using namespace boost::msm::front::euml; | |
21 | ||
22 | #include <iostream> | |
23 | #ifdef WIN32 | |
24 | #include "windows.h" | |
25 | #else | |
26 | #include <sys/time.h> | |
27 | #endif | |
28 | ||
29 | namespace // Concrete FSM implementation | |
30 | { | |
31 | // events | |
32 | BOOST_MSM_EUML_EVENT(play) | |
33 | BOOST_MSM_EUML_EVENT(end_pause) | |
34 | BOOST_MSM_EUML_EVENT(stop) | |
35 | BOOST_MSM_EUML_EVENT(pause) | |
36 | BOOST_MSM_EUML_EVENT(open_close) | |
37 | BOOST_MSM_EUML_EVENT(cd_detected) | |
38 | ||
39 | BOOST_MSM_EUML_ACTION(start_playback) | |
40 | { | |
41 | template <class FSM,class EVT,class SourceState,class TargetState> | |
42 | void operator()(EVT const& ,FSM&,SourceState& ,TargetState& ) | |
43 | { | |
44 | } | |
45 | }; | |
46 | BOOST_MSM_EUML_ACTION(open_drawer) | |
47 | { | |
48 | template <class FSM,class EVT,class SourceState,class TargetState> | |
49 | void operator()(EVT const& ,FSM&,SourceState& ,TargetState& ) | |
50 | { | |
51 | } | |
52 | }; | |
53 | BOOST_MSM_EUML_ACTION(close_drawer) | |
54 | { | |
55 | template <class FSM,class EVT,class SourceState,class TargetState> | |
56 | void operator()(EVT const& ,FSM&,SourceState& ,TargetState& ) | |
57 | { | |
58 | } | |
59 | }; | |
60 | BOOST_MSM_EUML_ACTION(store_cd_info) | |
61 | { | |
62 | template <class FSM,class EVT,class SourceState,class TargetState> | |
63 | void operator()(EVT const&, FSM& fsm ,SourceState& ,TargetState& ) | |
64 | { | |
65 | } | |
66 | }; | |
67 | BOOST_MSM_EUML_ACTION(stop_playback) | |
68 | { | |
69 | template <class FSM,class EVT,class SourceState,class TargetState> | |
70 | void operator()(EVT const& ,FSM&,SourceState& ,TargetState& ) | |
71 | { | |
72 | } | |
73 | }; | |
74 | BOOST_MSM_EUML_ACTION(pause_playback) | |
75 | { | |
76 | template <class FSM,class EVT,class SourceState,class TargetState> | |
77 | void operator()(EVT const& ,FSM&,SourceState& ,TargetState& ) | |
78 | { | |
79 | } | |
80 | }; | |
81 | BOOST_MSM_EUML_ACTION(resume_playback) | |
82 | { | |
83 | template <class FSM,class EVT,class SourceState,class TargetState> | |
84 | void operator()(EVT const& ,FSM&,SourceState& ,TargetState& ) | |
85 | { | |
86 | } | |
87 | }; | |
88 | BOOST_MSM_EUML_ACTION(stop_and_open) | |
89 | { | |
90 | template <class FSM,class EVT,class SourceState,class TargetState> | |
91 | void operator()(EVT const& ,FSM&,SourceState& ,TargetState& ) | |
92 | { | |
93 | } | |
94 | }; | |
95 | BOOST_MSM_EUML_ACTION(stopped_again) | |
96 | { | |
97 | template <class FSM,class EVT,class SourceState,class TargetState> | |
98 | void operator()(EVT const& ,FSM&,SourceState& ,TargetState& ) | |
99 | { | |
100 | } | |
101 | }; | |
102 | ||
103 | // The list of FSM states | |
104 | BOOST_MSM_EUML_STATE((),Empty) | |
105 | BOOST_MSM_EUML_STATE((),Open) | |
106 | BOOST_MSM_EUML_STATE((),Stopped) | |
107 | BOOST_MSM_EUML_STATE((),Playing) | |
108 | BOOST_MSM_EUML_STATE((),Paused) | |
109 | ||
110 | // replaces the old transition table | |
111 | BOOST_MSM_EUML_TRANSITION_TABLE(( | |
112 | Playing == Stopped + play / start_playback , | |
113 | Playing == Paused + end_pause / resume_playback , | |
114 | // +------------------------------------------------------------------------------+ | |
115 | Empty == Open + open_close / close_drawer , | |
116 | // +------------------------------------------------------------------------------+ | |
117 | Open == Empty + open_close / open_drawer , | |
118 | Open == Paused + open_close / stop_and_open , | |
119 | Open == Stopped + open_close / open_drawer , | |
120 | Open == Playing + open_close / stop_and_open , | |
121 | // +------------------------------------------------------------------------------+ | |
122 | Paused == Playing + pause / pause_playback , | |
123 | // +------------------------------------------------------------------------------+ | |
124 | Stopped == Playing + stop / stop_playback , | |
125 | Stopped == Paused + stop / stop_playback , | |
126 | Stopped == Empty + cd_detected / store_cd_info , | |
127 | Stopped == Stopped + stop / stopped_again | |
128 | // +------------------------------------------------------------------------------+ | |
129 | ),transition_table) | |
130 | ||
131 | BOOST_MSM_EUML_ACTION(Log_No_Transition) | |
132 | { | |
133 | template <class FSM,class Event> | |
134 | void operator()(Event const& e,FSM&,int state) | |
135 | { | |
136 | std::cout << "no transition from state " << state | |
137 | << " on event " << typeid(e).name() << std::endl; | |
138 | } | |
139 | }; | |
140 | ||
141 | // create a state machine "on the fly" | |
142 | BOOST_MSM_EUML_DECLARE_STATE_MACHINE(( transition_table, //STT | |
143 | init_ << Empty, // Init State | |
144 | no_action, // Entry | |
145 | no_action, // Exit | |
146 | attributes_ << no_attributes_, // Attributes | |
147 | configure_ << no_exception << no_msg_queue, // configuration | |
148 | Log_No_Transition // no_transition handler | |
149 | ), | |
150 | player_) //fsm name | |
151 | ||
152 | typedef msm::back::state_machine<player_> player; | |
153 | ||
154 | // | |
155 | // Testing utilities. | |
156 | // | |
157 | static char const* const state_names[] = { "Stopped", "Open", "Empty", "Playing", "Paused" }; | |
158 | ||
159 | void pstate(player const& p) | |
160 | { | |
161 | std::cout << " -> " << state_names[p.current_state()[0]] << std::endl; | |
162 | } | |
163 | ||
164 | } | |
165 | ||
166 | #ifndef WIN32 | |
167 | long mtime(struct timeval& tv1,struct timeval& tv2) | |
168 | { | |
169 | return (tv2.tv_sec-tv1.tv_sec) *1000000 + ((tv2.tv_usec-tv1.tv_usec)); | |
170 | } | |
171 | #endif | |
172 | ||
173 | ||
174 | int main() | |
175 | { | |
176 | // for timing | |
177 | #ifdef WIN32 | |
178 | LARGE_INTEGER res; | |
179 | ::QueryPerformanceFrequency(&res); | |
180 | LARGE_INTEGER li,li2; | |
181 | #else | |
182 | struct timeval tv1,tv2; | |
183 | gettimeofday(&tv1,NULL); | |
184 | #endif | |
185 | ||
186 | player p2; | |
187 | p2.start(); | |
188 | // for timing | |
189 | #ifdef WIN32 | |
190 | ::QueryPerformanceCounter(&li); | |
191 | #else | |
192 | gettimeofday(&tv1,NULL); | |
193 | #endif | |
194 | for (int i=0;i<100;++i) | |
195 | { | |
196 | p2.process_event(open_close); | |
197 | p2.process_event(open_close); | |
198 | p2.process_event(cd_detected); | |
199 | p2.process_event(play); | |
200 | p2.process_event(pause); | |
201 | // go back to Playing | |
202 | p2.process_event(end_pause); | |
203 | p2.process_event(pause); | |
204 | p2.process_event(stop); | |
205 | // event leading to the same state | |
206 | p2.process_event(stop); | |
207 | p2.process_event(open_close); | |
208 | p2.process_event(open_close); | |
209 | } | |
210 | #ifdef WIN32 | |
211 | ::QueryPerformanceCounter(&li2); | |
212 | #else | |
213 | gettimeofday(&tv2,NULL); | |
214 | #endif | |
215 | #ifdef WIN32 | |
216 | std::cout << "msm took in s:" << (double)(li2.QuadPart-li.QuadPart)/res.QuadPart <<"\n" <<std::endl; | |
217 | #else | |
218 | std::cout << "msm took in us:" << mtime(tv1,tv2) <<"\n" <<std::endl; | |
219 | #endif | |
220 | return 0; | |
221 | } | |
222 |