• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/msm/back/state_machine.hpp>
12 #include <boost/msm/front/state_machine_def.hpp>
13 #include <boost/msm/front/functor_row.hpp>
14 
15 namespace msm = boost::msm;
16 namespace mpl = boost::mpl;
17 using namespace msm::front;
18 
19 #include <iostream>
20 #ifdef WIN32
21 #include "windows.h"
22 #else
23 #include <sys/time.h>
24 #endif
25 
26 namespace test_fsm // Concrete FSM implementation
27 {
28     // events
29     struct play {};
30     struct end_pause {};
31     struct stop {};
32     struct pause {};
33     struct open_close {};
34     struct cd_detected{};
35 
36     // Concrete FSM implementation
37     struct player_ : public msm::front::state_machine_def<player_>
38     {
39         // no need for exception handling or message queue
40         typedef int no_exception_thrown;
41         typedef int no_message_queue;
42 
43         // The list of FSM states
44         struct Empty : public msm::front::state<>
45         {
46             // optional entry/exit methods
47             template <class Event,class FSM>
on_entrytest_fsm::player_::Empty48             void on_entry(Event const&,FSM& ) {/*std::cout << "entering: Empty" << std::endl;*/}
49             template <class Event,class FSM>
on_exittest_fsm::player_::Empty50             void on_exit(Event const&,FSM& ) {/*std::cout << "leaving: Empty" << std::endl;*/}
51         };
52         struct Open : public msm::front::state<>
53         {
54             template <class Event,class FSM>
on_entrytest_fsm::player_::Open55             void on_entry(Event const&,FSM& ) {/*std::cout << "entering: Open" << std::endl;*/}
56             template <class Event,class FSM>
on_exittest_fsm::player_::Open57             void on_exit(Event const&,FSM& ) {/*std::cout << "leaving: Open" << std::endl;*/}
58         };
59 
60         struct Stopped : public msm::front::state<>
61         {
62             // when stopped, the CD is loaded
63             template <class Event,class FSM>
on_entrytest_fsm::player_::Stopped64             void on_entry(Event const&,FSM& ) {/*std::cout << "entering: Stopped" << std::endl;*/}
65             template <class Event,class FSM>
on_exittest_fsm::player_::Stopped66             void on_exit(Event const&,FSM& ) {/*std::cout << "leaving: Stopped" << std::endl;*/}
67         };
68 
69         struct Playing : public msm::front::state<>
70         {
71             template <class Event,class FSM>
on_entrytest_fsm::player_::Playing72             void on_entry(Event const&,FSM& ) {/*std::cout << "entering: Playing" << std::endl;*/}
73             template <class Event,class FSM>
on_exittest_fsm::player_::Playing74             void on_exit(Event const&,FSM& ) {/*std::cout << "leaving: Playing" << std::endl;*/}
75         };
76 
77         // state not defining any entry or exit
78         struct Paused : public msm::front::state<>
79         {
80             template <class Event,class FSM>
on_entrytest_fsm::player_::Paused81             void on_entry(Event const&,FSM& ) {/*std::cout << "entering: Paused" << std::endl;*/}
82             template <class Event,class FSM>
on_exittest_fsm::player_::Paused83             void on_exit(Event const&,FSM& ) {/*std::cout << "leaving: Paused" << std::endl;*/}
84         };
85 
86         // the initial state of the player SM. Must be defined
87         typedef Empty initial_state;
88         // transition actions
89         struct start_playback
90         {
91             template <class FSM,class EVT,class SourceState,class TargetState>
operator ()test_fsm::player_::start_playback92             void operator()(EVT const& ,FSM&,SourceState& ,TargetState& )
93             {
94             }
95         };
96         struct open_drawer
97         {
98             template <class FSM,class EVT,class SourceState,class TargetState>
operator ()test_fsm::player_::open_drawer99             void operator()(EVT const& ,FSM&,SourceState& ,TargetState& )
100             {
101             }
102         };
103         struct close_drawer
104         {
105             template <class FSM,class EVT,class SourceState,class TargetState>
operator ()test_fsm::player_::close_drawer106             void operator()(EVT const& ,FSM&,SourceState& ,TargetState& )
107             {
108             }
109         };
110         struct store_cd_info
111         {
112             template <class FSM,class EVT,class SourceState,class TargetState>
operator ()test_fsm::player_::store_cd_info113             void operator()(EVT const&, FSM& fsm ,SourceState& ,TargetState& )
114             {
115             }
116         };
117         struct stop_playback
118         {
119             template <class FSM,class EVT,class SourceState,class TargetState>
operator ()test_fsm::player_::stop_playback120             void operator()(EVT const& ,FSM&,SourceState& ,TargetState& )
121             {
122             }
123         };
124         struct pause_playback
125         {
126             template <class FSM,class EVT,class SourceState,class TargetState>
operator ()test_fsm::player_::pause_playback127             void operator()(EVT const& ,FSM&,SourceState& ,TargetState& )
128             {
129             }
130         };
131         struct resume_playback
132         {
133             template <class FSM,class EVT,class SourceState,class TargetState>
operator ()test_fsm::player_::resume_playback134             void operator()(EVT const& ,FSM&,SourceState& ,TargetState& )
135             {
136             }
137         };
138         struct stop_and_open
139         {
140             template <class FSM,class EVT,class SourceState,class TargetState>
operator ()test_fsm::player_::stop_and_open141             void operator()(EVT const& ,FSM&,SourceState& ,TargetState& )
142             {
143             }
144         };
145         struct stopped_again
146         {
147             template <class FSM,class EVT,class SourceState,class TargetState>
operator ()test_fsm::player_::stopped_again148             void operator()(EVT const& ,FSM&,SourceState& ,TargetState& )
149             {
150             }
151         };
152         // guard conditions
153 
154         // Transition table for player
155         struct transition_table : mpl::vector<
156             //    Start     Event         Next      Action                 Guard
157             //    +---------+-------------+---------+---------------------+----------------------+
158               Row < Stopped , play        , Playing , start_playback                            >,
159               Row < Stopped , open_close  , Open    , open_drawer                               >,
160               Row < Stopped , stop        , Stopped , stopped_again                             >,
161             //    +---------+-------------+---------+---------------------+----------------------+
162               Row < Open    , open_close  , Empty   , close_drawer                              >,
163             //    +---------+-------------+---------+---------------------+----------------------+
164               Row < Empty   , open_close  , Open    , open_drawer                               >,
165               Row < Empty   , cd_detected , Stopped , store_cd_info                             >,
166             //    +---------+-------------+---------+---------------------+----------------------+
167               Row < Playing , stop        , Stopped , stop_playback                             >,
168               Row < Playing , pause       , Paused  , pause_playback                            >,
169               Row < Playing , open_close  , Open    , stop_and_open                             >,
170             //    +---------+-------------+---------+---------------------+----------------------+
171               Row < Paused  , end_pause   , Playing , resume_playback                           >,
172               Row < Paused  , stop        , Stopped , stop_playback                             >,
173               Row < Paused  , open_close  , Open    , stop_and_open                             >
174             //    +---------+-------------+---------+---------------------+----------------------+
175         > {};
176 
177         // Replaces the default no-transition response.
178         template <class FSM,class Event>
no_transitiontest_fsm::player_179         void no_transition(Event const& e, FSM&,int state)
180         {
181             std::cout << "no transition from state " << state
182                 << " on event " << typeid(e).name() << std::endl;
183         }
184     };
185     typedef msm::back::state_machine<player_> player;
186 
187     //
188     // Testing utilities.
189     //
190     static char const* const state_names[] = { "Stopped", "Open", "Empty", "Playing", "Paused" };
191 
pstate(player const & p)192     void pstate(player const& p)
193     {
194         std::cout << " -> " << state_names[p.current_state()[0]] << std::endl;
195     }
196 
197 }
198 
199 #ifndef WIN32
mtime(struct timeval & tv1,struct timeval & tv2)200 long mtime(struct timeval& tv1,struct timeval& tv2)
201 {
202     return (tv2.tv_sec-tv1.tv_sec) *1000000 + ((tv2.tv_usec-tv1.tv_usec));
203 }
204 #endif
205 
206 
main()207 int main()
208 {
209     // for timing
210 #ifdef WIN32
211     LARGE_INTEGER res;
212     ::QueryPerformanceFrequency(&res);
213     LARGE_INTEGER li,li2;
214 #else
215     struct timeval tv1,tv2;
216     gettimeofday(&tv1,NULL);
217 #endif
218     test_fsm::player p2;
219     p2.start();
220     // for timing
221 #ifdef WIN32
222     ::QueryPerformanceCounter(&li);
223 #else
224     gettimeofday(&tv1,NULL);
225 #endif
226     for (int i=0;i<100;++i)
227     {
228         p2.process_event(test_fsm::open_close());
229         p2.process_event(test_fsm::open_close());
230         p2.process_event(test_fsm::cd_detected());
231         p2.process_event(test_fsm::play());
232         p2.process_event(test_fsm::pause());
233         // go back to Playing
234         p2.process_event(test_fsm::end_pause());
235         p2.process_event(test_fsm::pause());
236         p2.process_event(test_fsm::stop());
237         // event leading to the same state
238         p2.process_event(test_fsm::stop());
239         p2.process_event(test_fsm::open_close());
240         p2.process_event(test_fsm::open_close());
241     }
242 #ifdef WIN32
243     ::QueryPerformanceCounter(&li2);
244 #else
245     gettimeofday(&tv2,NULL);
246 #endif
247 #ifdef WIN32
248     std::cout << "msm took in s:" << (double)(li2.QuadPart-li.QuadPart)/res.QuadPart <<"\n" <<std::endl;
249 #else
250     std::cout << "msm took in us:" <<  mtime(tv1,tv2) <<"\n" <<std::endl;
251 #endif
252     return 0;
253 }
254 
255