• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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()141 char GetKey()
142 {
143   char key;
144   std::cin >> key;
145   return key;
146 }
147 
148 
149 //////////////////////////////////////////////////////////////////////////////
main()150 int 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