• 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 
14 namespace msm = boost::msm;
15 namespace mpl = boost::mpl;
16 
17 #include <iostream>
18 #ifdef WIN32
19 #include "windows.h"
20 #else
21 #include <sys/time.h>
22 #endif
23 
24 namespace test_fsm // Concrete FSM implementation
25 {
26     // events
27     struct play {};
28     struct end_pause {};
29     struct stop {};
30     struct pause {};
31     struct open_close {};
32     struct cd_detected{};
33 
34     // Concrete FSM implementation
35     struct player_ : public msm::front::state_machine_def<player_>
36     {
37         // no need for exception handling or message queue
38         typedef int no_exception_thrown;
39         typedef int no_message_queue;
40 
41         // The list of FSM states
42         struct Empty : public msm::front::state<>
43         {
44             // optional entry/exit methods
45             template <class Event,class FSM>
on_entrytest_fsm::player_::Empty46             void on_entry(Event const&,FSM& ) {/*std::cout << "entering: Empty" << std::endl;*/}
47             template <class Event,class FSM>
on_exittest_fsm::player_::Empty48             void on_exit(Event const&,FSM& ) {/*std::cout << "leaving: Empty" << std::endl;*/}
49         };
50         struct Open : public msm::front::state<>
51         {
52             template <class Event,class FSM>
on_entrytest_fsm::player_::Open53             void on_entry(Event const&,FSM& ) {/*std::cout << "entering: Open" << std::endl;*/}
54             template <class Event,class FSM>
on_exittest_fsm::player_::Open55             void on_exit(Event const&,FSM& ) {/*std::cout << "leaving: Open" << std::endl;*/}
56         };
57 
58         struct Stopped : public msm::front::state<>
59         {
60             template <class Event,class FSM>
on_entrytest_fsm::player_::Stopped61             void on_entry(Event const&,FSM& ) {/*std::cout << "entering: Stopped" << std::endl;*/}
62             template <class Event,class FSM>
on_exittest_fsm::player_::Stopped63             void on_exit(Event const&,FSM& ) {/*std::cout << "leaving: Stopped" << std::endl;*/}
64         };
65 
66         struct Playing : public msm::front::state<>
67         {
68             template <class Event,class FSM>
on_entrytest_fsm::player_::Playing69             void on_entry(Event const&,FSM& ) {/*std::cout << "entering: Playing" << std::endl;*/}
70             template <class Event,class FSM>
on_exittest_fsm::player_::Playing71             void on_exit(Event const&,FSM& ) {/*std::cout << "leaving: Playing" << std::endl;*/}
72         };
73 
74         struct Paused : public msm::front::state<>
75         {
76             template <class Event,class FSM>
on_entrytest_fsm::player_::Paused77             void on_entry(Event const&,FSM& ) {/*std::cout << "entering: Paused" << std::endl;*/}
78             template <class Event,class FSM>
on_exittest_fsm::player_::Paused79             void on_exit(Event const&,FSM& ) {/*std::cout << "leaving: Paused" << std::endl;*/}
80         };
81 
82         // the initial state of the player SM. Must be defined
83         typedef Empty initial_state;
84         // transition actions
start_playbacktest_fsm::player_85         void start_playback(play const&)       {  }
open_drawertest_fsm::player_86         void open_drawer(open_close const&)    {  }
close_drawertest_fsm::player_87         void close_drawer(open_close const&)   {  }
store_cd_infotest_fsm::player_88         void store_cd_info(cd_detected const& cd) { }
stop_playbacktest_fsm::player_89         void stop_playback(stop const&)        {  }
pause_playbacktest_fsm::player_90         void pause_playback(pause const&)      { }
resume_playbacktest_fsm::player_91         void resume_playback(end_pause const&)      {  }
stop_and_opentest_fsm::player_92         void stop_and_open(open_close const&)  {  }
stopped_againtest_fsm::player_93         void stopped_again(stop const&){}
94         // guard conditions
95 
96         typedef player_ p; // makes transition table cleaner
97 
98         // Transition table for player
99         struct transition_table : mpl::vector<
100             //    Start     Event         Next      Action                 Guard
101             //    +---------+-------------+---------+---------------------+----------------------+
102               _row < Stopped , play        , Playing                      >,
103               _row < Stopped , open_close  , Open                             >,
104               _row < Stopped , stop        , Stopped                         >,
105             //    +---------+-------------+---------+---------------------+----------------------+
106               _row < Open    , open_close  , Empty                            >,
107             //    +---------+-------------+---------+---------------------+----------------------+
108               _row < Empty   , open_close  , Open                              >,
109               _row < Empty   , cd_detected , Stopped                         >,
110             //    +---------+-------------+---------+---------------------+----------------------+
111               _row < Playing , stop        , Stopped                         >,
112               _row < Playing , pause       , Paused                         >,
113               _row < Playing , open_close  , Open                            >,
114             //    +---------+-------------+---------+---------------------+----------------------+
115               _row < Paused  , end_pause   , Playing                      >,
116               _row < Paused  , stop        , Stopped                         >,
117               _row < Paused  , open_close  , Open                            >
118             //    +---------+-------------+---------+---------------------+----------------------+
119         > {};
120 
121         // Replaces the default no-transition response.
122         template <class FSM,class Event>
no_transitiontest_fsm::player_123         void no_transition(Event const& e, FSM&,int state)
124         {
125             std::cout << "no transition from state " << state
126                 << " on event " << typeid(e).name() << std::endl;
127         }
128     };
129     typedef msm::back::state_machine<player_> player;
130 
131     //
132     // Testing utilities.
133     //
134     static char const* const state_names[] = { "Stopped", "Open", "Empty", "Playing", "Paused" };
135 
pstate(player const & p)136     void pstate(player const& p)
137     {
138         std::cout << " -> " << state_names[p.current_state()[0]] << std::endl;
139     }
140 
141 }
142 
143 #ifndef WIN32
mtime(struct timeval & tv1,struct timeval & tv2)144 long mtime(struct timeval& tv1,struct timeval& tv2)
145 {
146     return (tv2.tv_sec-tv1.tv_sec) *1000000 + ((tv2.tv_usec-tv1.tv_usec));
147 }
148 #endif
149 
150 
main()151 int main()
152 {
153     // for timing
154 #ifdef WIN32
155     LARGE_INTEGER res;
156     ::QueryPerformanceFrequency(&res);
157     LARGE_INTEGER li,li2;
158 #else
159     struct timeval tv1,tv2;
160     gettimeofday(&tv1,NULL);
161 #endif
162 
163     test_fsm::player p2;
164     p2.start();
165     // for timing
166 #ifdef WIN32
167     ::QueryPerformanceCounter(&li);
168 #else
169     gettimeofday(&tv1,NULL);
170 #endif
171     for (int i=0;i<100;++i)
172     {
173         p2.process_event(test_fsm::open_close());
174         p2.process_event(test_fsm::open_close());
175         p2.process_event(test_fsm::cd_detected());
176         p2.process_event(test_fsm::play());
177         p2.process_event(test_fsm::pause());
178         // go back to Playing
179         p2.process_event(test_fsm::end_pause());
180         p2.process_event(test_fsm::pause());
181         p2.process_event(test_fsm::stop());
182         // event leading to the same state
183         p2.process_event(test_fsm::stop());
184         p2.process_event(test_fsm::open_close());
185         p2.process_event(test_fsm::open_close());
186     }
187 #ifdef WIN32
188     ::QueryPerformanceCounter(&li2);
189 #else
190     gettimeofday(&tv2,NULL);
191 #endif
192 #ifdef WIN32
193     std::cout << "msm took in s:" << (double)(li2.QuadPart-li.QuadPart)/res.QuadPart <<"\n" <<std::endl;
194 #else
195     std::cout << "msm took in us:" <<  mtime(tv1,tv2) <<"\n" <<std::endl;
196 #endif
197     return 0;
198 }
199 
200