Handcrafted.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  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. // This is a quick-and-dirty handcrafted state machine with two states and two
  8. // transitions employing GOF-visitation (two virtual calls per event).
  9. // It is used to make speed comparisons with Boost.Statechart machines.
  10. //////////////////////////////////////////////////////////////////////////////
  11. #include <boost/config.hpp>
  12. #include <iostream>
  13. #include <iomanip>
  14. #include <ctime>
  15. #ifdef BOOST_NO_STDC_NAMESPACE
  16. namespace std
  17. {
  18. using ::clock_t;
  19. using ::clock;
  20. }
  21. #endif
  22. #ifdef BOOST_INTEL
  23. # pragma warning( disable: 304 ) // access control not specified
  24. #endif
  25. //////////////////////////////////////////////////////////////////////////////
  26. class EvFlipBit;
  27. class state_base
  28. {
  29. public:
  30. virtual ~state_base() {};
  31. virtual const state_base & react( const EvFlipBit & toEvent ) const = 0;
  32. protected:
  33. state_base() {}
  34. };
  35. template< class Derived >
  36. class state : public state_base
  37. {
  38. public:
  39. state() : state_base() { }
  40. static const Derived & instance()
  41. {
  42. return instance_;
  43. }
  44. private:
  45. static const Derived instance_;
  46. };
  47. template< class Derived >
  48. const Derived state< Derived >::instance_;
  49. //////////////////////////////////////////////////////////////////////////////
  50. class event_base
  51. {
  52. public:
  53. virtual ~event_base() {}
  54. protected:
  55. event_base() {}
  56. public:
  57. virtual const state_base & send( const state_base & toState ) const = 0;
  58. };
  59. template< class Derived >
  60. class event : public event_base
  61. {
  62. protected:
  63. event() {}
  64. private:
  65. virtual const state_base & send( const state_base & toState ) const
  66. {
  67. return toState.react( *static_cast< const Derived * >( this ) );
  68. }
  69. };
  70. //////////////////////////////////////////////////////////////////////////////
  71. class EvFlipBit : public event< EvFlipBit > {
  72. public:
  73. EvFlipBit() : event < EvFlipBit >() { }
  74. };
  75. const EvFlipBit flip;
  76. class BitMachine
  77. {
  78. public:
  79. //////////////////////////////////////////////////////////////////////////
  80. BitMachine() : pCurrentState_( &Off::instance() ) {}
  81. void process_event( const event_base & evt )
  82. {
  83. pCurrentState_ = &evt.send( *pCurrentState_ );
  84. }
  85. private:
  86. //////////////////////////////////////////////////////////////////////////
  87. struct On : state< On >
  88. {
  89. On() : state<On>() { }
  90. virtual const state_base & react( const EvFlipBit & ) const
  91. {
  92. return Off::instance();
  93. }
  94. };
  95. struct Off : state< Off >
  96. {
  97. Off() : state<Off>() { }
  98. virtual const state_base & react( const EvFlipBit & ) const
  99. {
  100. return On::instance();
  101. }
  102. };
  103. const state_base * pCurrentState_;
  104. };
  105. //////////////////////////////////////////////////////////////////////////////
  106. char GetKey()
  107. {
  108. char key;
  109. std::cin >> key;
  110. return key;
  111. }
  112. //////////////////////////////////////////////////////////////////////////////
  113. int main()
  114. {
  115. // common prime factors of 2^n-1 for n in [1,8]
  116. const unsigned int noOfEvents = 3 * 3 * 5 * 7 * 17 * 31 * 127;
  117. unsigned long eventsSentTotal = 0;
  118. std::cout << "Boost.Statechart Handcrafted example\n";
  119. std::cout << "Machine configuration: " << 2 <<
  120. " states interconnected with " << 2 << " transitions.\n\n";
  121. std::cout << "p<CR>: Performance test\n";
  122. std::cout << "e<CR>: Exits the program\n\n";
  123. std::cout <<
  124. "You may chain commands, e.g. pe<CR> performs a test and then exits the program\n\n";
  125. BitMachine bitMachine;
  126. char key = GetKey();
  127. while ( key != 'e' )
  128. {
  129. switch ( key )
  130. {
  131. case 'p':
  132. {
  133. std::cout << "\nSending " << noOfEvents <<
  134. " events. Please wait...\n";
  135. const unsigned long startEvents2 = eventsSentTotal;
  136. const std::clock_t startTime2 = std::clock();
  137. for ( unsigned int eventNo = 0; eventNo < noOfEvents; ++eventNo )
  138. {
  139. bitMachine.process_event( flip );
  140. ++eventsSentTotal;
  141. }
  142. const std::clock_t elapsedTime2 = std::clock() - startTime2;
  143. const unsigned int eventsSent2 = eventsSentTotal - startEvents2;
  144. std::cout << "Time to dispatch one event and\n" <<
  145. "perform the resulting transition: ";
  146. std::cout << elapsedTime2 * 1000.0 / eventsSent2 << " microseconds\n\n";
  147. }
  148. break;
  149. default:
  150. {
  151. std::cout << "Invalid key!\n";
  152. }
  153. }
  154. key = GetKey();
  155. }
  156. return 0;
  157. }