1 //////////////////////////////////////////////////////////////////////////////
2 // Copyright 2002-2006 Andreas Huber Doenni
3 // Distributed under the Boost Software License, Version 1.0. (See accompany-
4 // ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 //////////////////////////////////////////////////////////////////////////////
6
7
8
9 //////////////////////////////////////////////////////////////////////////////
10 // The following code implements the state-machine (this is the version
11 // discussed in the tutorial):
12 //
13 // --------------------------------
14 // | |
15 // | O Active |
16 // | | |<----
17 // | v | | EvReset
18 // | ---------------------------- | |
19 // | | | |-----
20 // | | Stopped | |
21 // | ---------------------------- |
22 // | | ^ |
23 // | | EvStartStop | EvStartStop |<-----O
24 // | v | |
25 // | ---------------------------- |
26 // | | | |
27 // | | Running | |
28 // | ---------------------------- |
29 // --------------------------------
30
31
32
33 #include <boost/statechart/event.hpp>
34 #include <boost/statechart/state_machine.hpp>
35 #include <boost/statechart/simple_state.hpp>
36 #include <boost/statechart/transition.hpp>
37
38 #include <boost/config.hpp>
39
40 #include <ctime>
41 #include <iostream>
42
43 #ifdef BOOST_NO_STDC_NAMESPACE
44 namespace std
45 {
46 using ::time;
47 using ::difftime;
48 using ::time_t;
49 }
50 #endif
51
52 #ifdef BOOST_INTEL
53 # pragma warning( disable: 304 ) // access control not specified
54 # pragma warning( disable: 444 ) // destructor for base is not virtual
55 # pragma warning( disable: 981 ) // operands are evaluated in unspecified order
56 #endif
57
58
59
60 namespace sc = boost::statechart;
61
62
63
64 //////////////////////////////////////////////////////////////////////////////
65 struct EvStartStop : sc::event< EvStartStop > {};
66 struct EvReset : sc::event< EvReset > {};
67
68 struct IElapsedTime
69 {
70 virtual double ElapsedTime() const = 0;
71 };
72
73 struct Active;
74 struct StopWatch : sc::state_machine< StopWatch, Active > {};
75
76 struct Stopped;
77 struct Active : sc::simple_state< Active, StopWatch, Stopped >
78 {
79 public:
80 typedef sc::transition< EvReset, Active > reactions;
81
ActiveActive82 Active() : elapsedTime_( 0.0 ) {}
83
ElapsedTimeActive84 double & ElapsedTime()
85 {
86 return elapsedTime_;
87 }
88
ElapsedTimeActive89 double ElapsedTime() const
90 {
91 return elapsedTime_;
92 }
93
94 private:
95 double elapsedTime_;
96 };
97
98 struct Running : IElapsedTime, sc::simple_state< Running, Active >
99 {
100 public:
101 typedef sc::transition< EvStartStop, Stopped > reactions;
102
RunningRunning103 Running() : startTime_( std::time( 0 ) ) {}
104
~RunningRunning105 ~Running()
106 {
107 context< Active >().ElapsedTime() = ElapsedTime();
108 }
109
ElapsedTimeRunning110 virtual double ElapsedTime() const
111 {
112 return context< Active >().ElapsedTime() +
113 std::difftime( std::time( 0 ), startTime_ );
114 }
115
116 private:
117 std::time_t startTime_;
118 };
119
120 struct Stopped : IElapsedTime, sc::simple_state< Stopped, Active >
121 {
122 typedef sc::transition< EvStartStop, Running > reactions;
123
ElapsedTimeStopped124 virtual double ElapsedTime() const
125 {
126 return context< Active >().ElapsedTime();
127 }
128 };
129
130
131 //////////////////////////////////////////////////////////////////////////////
GetKey()132 char GetKey()
133 {
134 char key;
135 std::cin >> key;
136 return key;
137 }
138
139
140 //////////////////////////////////////////////////////////////////////////////
main()141 int main()
142 {
143 std::cout << "Boost.Statechart StopWatch example\n\n";
144 std::cout << "s<CR>: Starts/Stops stop watch\n";
145 std::cout << "r<CR>: Resets stop watch\n";
146 std::cout << "d<CR>: Displays the elapsed time in seconds\n";
147 std::cout << "e<CR>: Exits the program\n\n";
148 std::cout << "You may chain commands, e.g. rs<CR> resets and starts stop watch\n\n";
149
150 StopWatch stopWatch;
151 stopWatch.initiate();
152
153 char key = GetKey();
154
155 while ( key != 'e' )
156 {
157 switch( key )
158 {
159 case 'r':
160 {
161 stopWatch.process_event( EvReset() );
162 }
163 break;
164
165 case 's':
166 {
167 stopWatch.process_event( EvStartStop() );
168 }
169 break;
170
171 case 'd':
172 {
173 std::cout << "Elapsed time: " <<
174 stopWatch.state_cast< const IElapsedTime & >().ElapsedTime() << "\n";
175 }
176 break;
177
178 default:
179 {
180 std::cout << "Invalid key!\n";
181 }
182 break;
183 }
184
185 key = GetKey();
186 }
187
188 return 0;
189 }
190