Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/libs/statechart/example/BitMachine/BitMachine.cpp @ 29

Last change on this file since 29 was 29, checked in by landauf, 17 years ago

updated boost from 1_33_1 to 1_34_1

File size: 7.7 KB
Line 
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#define NO_OF_BITS 3
11//////////////////////////////////////////////////////////////////////////////
12// This program demonstrates the fact that measures must be taken to hide some
13// of the complexity (e.g. in separate .cpp file) of a Boost.Statechart state
14// machine once a certain size is reached.
15// For this purpose, a state machine with exactly 2^NO_OF_BITS states (i.e.
16// BitState< 0 > .. BitState< 2^NO_OF_BITS - 1 >) is generated. For the events
17// EvFlipBit< 0 > .. EvFlipBit< NO_OF_BITS - 1 > there is a transition from
18// each state to the state with the corresponding bit toggled. That is, there
19// is a total of 2^NO_OF_BITS * NO_OF_BITS transitions.
20// E.g. if the state machine is currently in state BitState< 5 > and receives
21// EvFlipBit< 2 >, it transitions to state BitState< 1 >. If it is in
22// BitState< 15 > and receives EvFlipBit< 4 > it transitions to BitState< 31 >
23// etc.
24// The maximum size of such a state machine depends on your compiler. The
25// following table gives upper limits for NO_OF_BITS. From this, rough
26// estimates for the maximum size of any "naively" implemented Boost.Statechart
27// machine (i.e. no attempt is made to hide inner state implementation in a
28// .cpp file) can be deduced.
29//
30// NOTE: Due to the fact that the amount of generated code more than
31// *doubles* each time NO_OF_BITS is *incremented*, build times on most
32// compilers soar when NO_OF_BITS > 6.
33//
34// Compiler      | max. NO_OF_BITS b | max. states s  |
35// --------------|-------------------|----------------|
36// MSVC 7.1      |      b < 6        |  32 < s <  64  |
37// GCC 3.4.2 (1) |      b < 8        | 128 < s < 256  |
38//
39// (1) This is a practical rather than a hard limit, caused by a compiler
40//     memory footprint that was significantly larger than the 1GB physical
41//     memory installed in the test machine. The resulting frequent swapping
42//     led to compilation times of hours rather than minutes.
43//////////////////////////////////////////////////////////////////////////////
44
45
46
47#include "UniqueObject.hpp"
48
49#include <boost/statechart/event.hpp>
50#include <boost/statechart/simple_state.hpp>
51#include <boost/statechart/state_machine.hpp>
52#include <boost/statechart/transition.hpp>
53
54#include <boost/mpl/list.hpp>
55#include <boost/mpl/front_inserter.hpp>
56#include <boost/mpl/transform_view.hpp>
57#include <boost/mpl/copy.hpp>
58#include <boost/mpl/range_c.hpp>
59#include <boost/mpl/integral_c.hpp>
60#include <boost/mpl/shift_left.hpp>
61#include <boost/mpl/bitxor.hpp>
62#include <boost/mpl/for_each.hpp>
63#include <boost/mpl/placeholders.hpp>
64#include <boost/mpl/aux_/lambda_support.hpp>
65
66#include <boost/config.hpp>
67#include <boost/intrusive_ptr.hpp>
68
69#include <iostream>
70#include <iomanip>
71#include <cstddef> // size_t
72
73#ifdef BOOST_INTEL
74#  pragma warning( disable: 304 ) // access control not specified
75#  pragma warning( disable: 444 ) // destructor for base is not virtual
76#  pragma warning( disable: 981 ) // operands are evaluated in unspecified order
77#endif
78
79
80
81namespace sc = boost::statechart;
82namespace mpl = boost::mpl;
83
84
85
86//////////////////////////////////////////////////////////////////////////////
87struct IDisplay
88{
89  virtual void Display() const = 0;
90};
91
92//////////////////////////////////////////////////////////////////////////////
93template< class BitNo >
94struct EvFlipBit : sc::event< EvFlipBit< BitNo > > {};
95
96template< class StateNo >
97struct BitState;
98
99struct BitMachine : sc::state_machine<
100  BitMachine, BitState< mpl::integral_c< unsigned int, 0 > > > {};
101
102template< class BitNo, class StateNo >
103struct FlipTransition
104{
105  private:
106    typedef typename mpl::bitxor_< 
107      StateNo, 
108      mpl::shift_left< mpl::integral_c< unsigned int, 1 >, BitNo >
109    >::type NextStateNo;
110
111  public:
112    typedef typename sc::transition<
113      EvFlipBit< BitNo >, BitState< NextStateNo > > type;
114
115    BOOST_MPL_AUX_LAMBDA_SUPPORT( 2, FlipTransition, (BitNo, StateNo) );
116};
117
118//////////////////////////////////////////////////////////////////////////////
119void DisplayBits( unsigned int number )
120{
121  char buffer[ NO_OF_BITS + 1 ];
122  buffer[ NO_OF_BITS ] = 0;
123
124  for ( unsigned int bit = 0; bit < NO_OF_BITS; ++bit )
125  {
126    buffer[ bit ] = number & ( 1 << ( NO_OF_BITS - bit - 1 ) ) ? '1' : '0';
127  }
128
129  std::cout << "Current state: " << std::setw( 4 ) <<
130    number << " (" << buffer << ")" << std::endl;
131}
132
133template< class StateNo >
134struct BitState : sc::simple_state< BitState< StateNo >, BitMachine >,
135  UniqueObject< BitState< StateNo > >, IDisplay
136{
137  void * operator new( std::size_t size )
138  {
139    return UniqueObject< BitState< StateNo > >::operator new( size );
140  }
141
142  void operator delete( void * p, std::size_t size )
143  {
144    UniqueObject< BitState< StateNo > >::operator delete( p, size );
145  }
146
147  typedef typename mpl::copy<
148    typename mpl::transform_view<
149      mpl::range_c< unsigned int, 0, NO_OF_BITS >,
150      FlipTransition< mpl::placeholders::_, StateNo > >::type,
151    mpl::front_inserter< mpl::list<> >
152  >::type reactions;
153
154  virtual void Display() const
155  {
156    DisplayBits( StateNo::value );
157  }
158};
159
160
161void DisplayMachineState( const BitMachine & bitMachine )
162{
163  bitMachine.state_cast< const IDisplay & >().Display();
164}
165
166//////////////////////////////////////////////////////////////////////////////
167boost::intrusive_ptr< const sc::event_base > pFlipBitEvents[ NO_OF_BITS ];
168
169struct EventInserter
170{
171  template< class BitNo >
172  void operator()( const BitNo & )
173  {
174    pFlipBitEvents[ BitNo::value ] = new EvFlipBit< BitNo >();
175  }
176};
177
178void FillEventArray()
179{
180  mpl::for_each< mpl::range_c< unsigned int, 0, NO_OF_BITS > >(
181    EventInserter() );
182}
183
184//////////////////////////////////////////////////////////////////////////////
185void VisitAllStates( BitMachine & bitMachine, unsigned int msb )
186{
187  if ( msb > 0 )
188  {
189    VisitAllStates( bitMachine, msb - 1 );
190  }
191
192  bitMachine.process_event( *pFlipBitEvents[ msb ] );
193  DisplayMachineState( bitMachine );
194
195  if ( msb > 0 )
196  {
197    VisitAllStates( bitMachine, msb - 1 );
198  }
199}
200
201//////////////////////////////////////////////////////////////////////////////
202char GetKey()
203{
204  char key;
205  std::cin >> key;
206  return key;
207}
208
209
210//////////////////////////////////////////////////////////////////////////////
211int main()
212{
213  FillEventArray();
214
215  const unsigned int noOfStates = 1 << NO_OF_BITS;
216  std::cout << "Boost.Statechart BitMachine example\n";
217  std::cout << "Machine configuration: " << noOfStates <<
218    " states interconnected with " << noOfStates * NO_OF_BITS <<
219    " transitions.\n\n";
220
221  for ( unsigned int bit = 0; bit < NO_OF_BITS; ++bit )
222  {
223    std::cout << bit - 0 << "<CR>: Flips bit " << bit - 0 << "\n";
224  }
225
226  std::cout << "a<CR>: Goes through all states automatically\n";
227  std::cout << "e<CR>: Exits the program\n\n";
228  std::cout << "You may chain commands, e.g. 31<CR> flips bits 3 and 1\n\n";
229
230
231  BitMachine bitMachine;
232  bitMachine.initiate();
233
234  char key = GetKey();
235
236  while ( key != 'e' )
237  {
238    if ( ( key >= '0' ) && ( key < static_cast< char >( '0' + NO_OF_BITS ) ) )
239    {
240      bitMachine.process_event( *pFlipBitEvents[ key - '0' ] );
241      DisplayMachineState( bitMachine );
242    }
243    else
244    {
245      switch( key )
246      {
247        case 'a':
248        {
249          VisitAllStates( bitMachine, NO_OF_BITS - 1 );
250        }
251        break;
252
253        default:
254        {
255          std::cout << "Invalid key!\n";
256        }
257      }
258    }
259
260    key = GetKey();
261  }
262
263  return 0;
264}
Note: See TracBrowser for help on using the repository browser.