StopWatch2.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  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. // The following code implements the state-machine (this version details an
  8. // alternative way of retrieving the elapsed time from the main program):
  9. //
  10. // --------------------------------
  11. // | |
  12. // | O Active |
  13. // | | |<----
  14. // | v | | EvReset
  15. // | ---------------------------- | |
  16. // | | | |-----
  17. // | | Stopped | |
  18. // | ---------------------------- |
  19. // | | ^ |
  20. // | | EvStartStop | EvStartStop |<-----O
  21. // | v | |
  22. // | ---------------------------- |
  23. // | | | |
  24. // | | Running | |
  25. // | ---------------------------- |
  26. // --------------------------------
  27. #include <boost/statechart/event.hpp>
  28. #include <boost/statechart/state_machine.hpp>
  29. #include <boost/statechart/simple_state.hpp>
  30. #include <boost/statechart/transition.hpp>
  31. #include <boost/statechart/custom_reaction.hpp>
  32. #include <boost/mpl/list.hpp>
  33. #include <boost/config.hpp>
  34. #include <ctime>
  35. #include <iostream>
  36. #ifdef BOOST_NO_STDC_NAMESPACE
  37. namespace std
  38. {
  39. using ::time;
  40. using ::difftime;
  41. using ::time_t;
  42. }
  43. #endif
  44. #ifdef BOOST_INTEL
  45. # pragma warning( disable: 304 ) // access control not specified
  46. # pragma warning( disable: 444 ) // destructor for base is not virtual
  47. # pragma warning( disable: 981 ) // operands are evaluated in unspecified order
  48. #endif
  49. namespace sc = boost::statechart;
  50. namespace mpl = boost::mpl;
  51. struct EvStartStop : sc::event< EvStartStop > {};
  52. struct EvReset : sc::event< EvReset > {};
  53. struct EvGetElapsedTime : sc::event< EvGetElapsedTime >
  54. {
  55. public:
  56. EvGetElapsedTime( double & time ) : time_( time ) {}
  57. void Assign( double time ) const
  58. {
  59. time_ = time;
  60. }
  61. private:
  62. double & time_;
  63. };
  64. struct Active;
  65. struct StopWatch : sc::state_machine< StopWatch, Active > {};
  66. struct Stopped;
  67. struct Active : sc::simple_state< Active, StopWatch, Stopped >
  68. {
  69. public:
  70. typedef sc::transition< EvReset, Active > reactions;
  71. Active() : elapsedTime_( 0.0 ) {}
  72. double & ElapsedTime()
  73. {
  74. return elapsedTime_;
  75. }
  76. double ElapsedTime() const
  77. {
  78. return elapsedTime_;
  79. }
  80. private:
  81. double elapsedTime_;
  82. };
  83. struct Running : sc::simple_state< Running, Active >
  84. {
  85. public:
  86. typedef mpl::list<
  87. sc::custom_reaction< EvGetElapsedTime >,
  88. sc::transition< EvStartStop, Stopped >
  89. > reactions;
  90. Running() : startTime_( std::time( 0 ) ) {}
  91. ~Running()
  92. {
  93. context< Active >().ElapsedTime() = ElapsedTime();
  94. }
  95. sc::result react( const EvGetElapsedTime & evt )
  96. {
  97. evt.Assign( ElapsedTime() );
  98. return discard_event();
  99. }
  100. private:
  101. double ElapsedTime() const
  102. {
  103. return context< Active >().ElapsedTime() +
  104. std::difftime( std::time( 0 ), startTime_ );
  105. }
  106. std::time_t startTime_;
  107. };
  108. struct Stopped : sc::simple_state< Stopped, Active >
  109. {
  110. typedef mpl::list<
  111. sc::custom_reaction< EvGetElapsedTime >,
  112. sc::transition< EvStartStop, Running >
  113. > reactions;
  114. sc::result react( const EvGetElapsedTime & evt )
  115. {
  116. evt.Assign( context< Active >().ElapsedTime() );
  117. return discard_event();
  118. }
  119. };
  120. namespace
  121. {
  122. char GetKey()
  123. {
  124. char key;
  125. std::cin >> key;
  126. return key;
  127. }
  128. }
  129. int main()
  130. {
  131. std::cout << "Boost.Statechart StopWatch example\n\n";
  132. std::cout << "s<CR>: Starts/Stops stop watch\n";
  133. std::cout << "r<CR>: Resets stop watch\n";
  134. std::cout << "d<CR>: Displays the elapsed time in seconds\n";
  135. std::cout << "e<CR>: Exits the program\n\n";
  136. std::cout << "You may chain commands, e.g. rs<CR> resets and starts stop watch\n\n";
  137. StopWatch stopWatch;
  138. stopWatch.initiate();
  139. char key = GetKey();
  140. while ( key != 'e' )
  141. {
  142. switch( key )
  143. {
  144. case 'r':
  145. {
  146. stopWatch.process_event( EvReset() );
  147. }
  148. break;
  149. case 's':
  150. {
  151. stopWatch.process_event( EvStartStop() );
  152. }
  153. break;
  154. case 'd':
  155. {
  156. double elapsedTime = 0.0;
  157. stopWatch.process_event( EvGetElapsedTime( elapsedTime ) );
  158. std::cout << "Elapsed time: " << elapsedTime << "\n";
  159. }
  160. break;
  161. default:
  162. {
  163. std::cout << "Invalid key!\n";
  164. }
  165. break;
  166. }
  167. key = GetKey();
  168. }
  169. return 0;
  170. }