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