mirror of
https://github.com/boostorg/statechart.git
synced 2026-01-29 20:12:08 +00:00
Simplified the BitMachine example (the performance measurement functions are no longer needed)
[SVN r30773]
This commit is contained in:
@@ -7,11 +7,7 @@
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#ifndef NO_OF_BITS
|
||||
# define NO_OF_BITS 4
|
||||
#endif
|
||||
// #define CUSTOMIZE_MEMORY_MANAGEMENT
|
||||
// #define BOOST_STATECHART_USE_NATIVE_RTTI
|
||||
#define NO_OF_BITS 5
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// This program demonstrates the fact that measures must be taken to hide some
|
||||
// of the complexity (e.g. in separate .cpp file) of a Boost.Statechart state
|
||||
@@ -48,55 +44,30 @@
|
||||
|
||||
|
||||
|
||||
#ifdef CUSTOMIZE_MEMORY_MANAGEMENT
|
||||
# include "UniqueObject.hpp"
|
||||
#endif
|
||||
#include "UniqueObject.hpp"
|
||||
|
||||
#include <boost/statechart/event.hpp>
|
||||
#include <boost/statechart/simple_state.hpp>
|
||||
#include <boost/statechart/state_machine.hpp>
|
||||
#include <boost/statechart/transition.hpp>
|
||||
#include <boost/statechart/custom_reaction.hpp>
|
||||
|
||||
#include <boost/mpl/list.hpp>
|
||||
#include <boost/mpl/push_front.hpp>
|
||||
#include <boost/mpl/reverse.hpp>
|
||||
#include <boost/mpl/transform.hpp>
|
||||
#include <boost/mpl/fold.hpp>
|
||||
#include <boost/mpl/integral_c.hpp>
|
||||
#include <boost/mpl/front_inserter.hpp>
|
||||
#include <boost/mpl/transform_view.hpp>
|
||||
#include <boost/mpl/copy.hpp>
|
||||
#include <boost/mpl/range_c.hpp>
|
||||
#include <boost/mpl/integral_c.hpp>
|
||||
#include <boost/mpl/shift_left.hpp>
|
||||
#include <boost/mpl/bitxor.hpp>
|
||||
#include <boost/mpl/for_each.hpp>
|
||||
#include <boost/mpl/placeholders.hpp>
|
||||
#include <boost/mpl/aux_/lambda_support.hpp>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/intrusive_ptr.hpp>
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning( push )
|
||||
# pragma warning( disable: 4127 ) // conditional expression is constant
|
||||
# pragma warning( disable: 4800 ) // forcing value to bool 'true' or 'false'
|
||||
#endif
|
||||
|
||||
#ifdef CUSTOMIZE_MEMORY_MANAGEMENT
|
||||
# define BOOST_NO_MT
|
||||
# include <boost/pool/pool_alloc.hpp>
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning( pop )
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <ctime>
|
||||
|
||||
#ifdef BOOST_NO_STDC_NAMESPACE
|
||||
namespace std
|
||||
{
|
||||
using ::clock_t;
|
||||
using ::clock;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef BOOST_INTEL
|
||||
# pragma warning( disable: 304 ) // access control not specified
|
||||
@@ -108,195 +79,143 @@ namespace std
|
||||
|
||||
namespace sc = boost::statechart;
|
||||
namespace mpl = boost::mpl;
|
||||
using namespace mpl::placeholders;
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
template< unsigned int bitNo >
|
||||
struct EvFlipBit : sc::event< EvFlipBit< bitNo > > {};
|
||||
|
||||
template< unsigned int stateNo >
|
||||
struct BitState;
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#ifdef CUSTOMIZE_MEMORY_MANAGEMENT
|
||||
struct BitMachine : sc::state_machine< BitMachine, BitState< 0 >,
|
||||
boost::fast_pool_allocator< int > > {};
|
||||
#else
|
||||
struct BitMachine : sc::state_machine< BitMachine, BitState< 0 > > {};
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
struct IDisplay
|
||||
{
|
||||
virtual void Display() const = 0;
|
||||
};
|
||||
|
||||
namespace
|
||||
{
|
||||
const unsigned int noOfStates = 1 << NO_OF_BITS;
|
||||
const unsigned int noOfTransitions = noOfStates * NO_OF_BITS;
|
||||
|
||||
// common prime factors of 2^n-1 for n in [1,8]
|
||||
const unsigned int noOfEvents = 3 * 3 * 5 * 7 * 17 * 31 * 127;
|
||||
const unsigned int noOfLaps = noOfEvents / ( noOfStates - 1 );
|
||||
|
||||
unsigned long eventsSentTotal = 0;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void DisplayBits( unsigned int number )
|
||||
{
|
||||
char buffer[ NO_OF_BITS + 1 ];
|
||||
buffer[ NO_OF_BITS ] = 0;
|
||||
|
||||
for ( unsigned int bit = 0; bit < NO_OF_BITS; ++bit )
|
||||
{
|
||||
buffer[ bit ] = number & ( 1 << ( NO_OF_BITS - bit - 1 ) ) ? '1' : '0';
|
||||
}
|
||||
|
||||
std::cout << "Current state: " << std::setw( 4 ) <<
|
||||
number << " (" << buffer << ")" << std::endl;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void DisplayMachineState( const BitMachine & bitMachine )
|
||||
{
|
||||
bitMachine.state_cast< const IDisplay & >().Display();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
boost::intrusive_ptr< const sc::event_base > pFlipBitEvents[ NO_OF_BITS ];
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
template< unsigned int arraySize >
|
||||
void FillEventArray()
|
||||
{
|
||||
pFlipBitEvents[ arraySize - 1 ] =
|
||||
boost::intrusive_ptr< const sc::event_base >(
|
||||
new EvFlipBit< arraySize - 1 >() );
|
||||
FillEventArray< arraySize - 1 >();
|
||||
}
|
||||
|
||||
template<>
|
||||
void FillEventArray< 0 >() {}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
template< typename T >
|
||||
T AvoidConstantWarning( T value ) { return value; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
template< unsigned int msb, bool display >
|
||||
void VisitAllStates( BitMachine & bitMachine )
|
||||
{
|
||||
VisitAllStates< msb - 1, display >( bitMachine );
|
||||
bitMachine.process_event( *pFlipBitEvents[ msb ] );
|
||||
++eventsSentTotal;
|
||||
|
||||
if ( AvoidConstantWarning( display ) )
|
||||
{
|
||||
DisplayMachineState( bitMachine );
|
||||
}
|
||||
|
||||
VisitAllStates< msb - 1, display >( bitMachine );
|
||||
}
|
||||
|
||||
template<>
|
||||
void VisitAllStates< 0, false >( BitMachine & bitMachine )
|
||||
{
|
||||
bitMachine.process_event( *pFlipBitEvents[ 0 ] );
|
||||
++eventsSentTotal;
|
||||
}
|
||||
|
||||
template<>
|
||||
void VisitAllStates< 0, true >( BitMachine & bitMachine )
|
||||
{
|
||||
bitMachine.process_event( *pFlipBitEvents[ 0 ] );
|
||||
++eventsSentTotal;
|
||||
DisplayMachineState( bitMachine );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
char GetKey()
|
||||
{
|
||||
char key;
|
||||
std::cin >> key;
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
template< class BitNo >
|
||||
struct EvFlipBit : sc::event< EvFlipBit< BitNo > > {};
|
||||
|
||||
template< class StateNo >
|
||||
struct BitState;
|
||||
|
||||
struct BitMachine : sc::state_machine<
|
||||
BitMachine, BitState< mpl::integral_c< unsigned int, 0 > > > {};
|
||||
|
||||
template< class BitNo, class StateNo >
|
||||
struct FlipTransition
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(
|
||||
unsigned int, nextStateNo=StateNo::value ^ ( 1 << BitNo::value ) );
|
||||
BOOST_STATIC_CONSTANT( unsigned int, bitNo=BitNo::value );
|
||||
|
||||
typedef sc::transition<
|
||||
EvFlipBit< bitNo >,
|
||||
BitState< nextStateNo > > type;
|
||||
|
||||
BOOST_MPL_AUX_LAMBDA_SUPPORT( 2, FlipTransition, (BitNo, StateNo) )
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
template< unsigned int stateNo >
|
||||
struct FlipTransitionList
|
||||
{
|
||||
private:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
typedef mpl::fold<
|
||||
mpl::range_c< unsigned int, 0, NO_OF_BITS >,
|
||||
mpl::list<>, mpl::push_front< _, _ > >::type
|
||||
BitNumbers;
|
||||
typedef typename mpl::bitxor_<
|
||||
StateNo,
|
||||
mpl::shift_left< mpl::integral_c< unsigned int, 1 >, BitNo >
|
||||
>::type NextStateNo;
|
||||
|
||||
public:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
typedef typename mpl::transform< BitNumbers,
|
||||
FlipTransition< _, mpl::integral_c< unsigned int, stateNo > > >::type type;
|
||||
typedef typename sc::transition<
|
||||
EvFlipBit< BitNo >, BitState< NextStateNo > > type;
|
||||
|
||||
BOOST_MPL_AUX_LAMBDA_SUPPORT( 2, FlipTransition, (BitNo, StateNo) );
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
template< unsigned int stateNo >
|
||||
struct BitState : sc::simple_state< BitState< stateNo >, BitMachine >,
|
||||
#ifdef CUSTOMIZE_MEMORY_MANAGEMENT
|
||||
IDisplay, UniqueObject< BitState< stateNo > >
|
||||
#else
|
||||
IDisplay
|
||||
#endif
|
||||
template< class StateNo >
|
||||
struct BitState : sc::simple_state< BitState< StateNo >, BitMachine >,
|
||||
UniqueObject< BitState< StateNo > >, IDisplay
|
||||
{
|
||||
#ifdef CUSTOMIZE_MEMORY_MANAGEMENT
|
||||
static void * operator new( size_t size )
|
||||
void * operator new( size_t size )
|
||||
{
|
||||
return UniqueObject< BitState< stateNo > >::operator new( size );
|
||||
return UniqueObject< BitState< StateNo > >::operator new( size );
|
||||
}
|
||||
|
||||
static void operator delete( void * p, size_t size )
|
||||
void operator delete( void * p, size_t size )
|
||||
{
|
||||
UniqueObject< BitState< stateNo > >::operator delete( p, size );
|
||||
UniqueObject< BitState< StateNo > >::operator delete( p, size );
|
||||
}
|
||||
#endif
|
||||
|
||||
typedef typename FlipTransitionList< stateNo >::type reactions;
|
||||
typedef typename mpl::copy<
|
||||
typename mpl::transform_view<
|
||||
mpl::range_c< unsigned int, 0, NO_OF_BITS >,
|
||||
FlipTransition< mpl::placeholders::_, StateNo > >::type,
|
||||
mpl::front_inserter< mpl::list<> >
|
||||
>::type reactions;
|
||||
|
||||
virtual void Display() const
|
||||
{
|
||||
DisplayBits( stateNo );
|
||||
DisplayBits( StateNo::value );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
void DisplayBits( unsigned int number )
|
||||
{
|
||||
char buffer[ NO_OF_BITS + 1 ];
|
||||
buffer[ NO_OF_BITS ] = 0;
|
||||
|
||||
for ( unsigned int bit = 0; bit < NO_OF_BITS; ++bit )
|
||||
{
|
||||
buffer[ bit ] = number & ( 1 << ( NO_OF_BITS - bit - 1 ) ) ? '1' : '0';
|
||||
}
|
||||
|
||||
std::cout << "Current state: " << std::setw( 4 ) <<
|
||||
number << " (" << buffer << ")" << std::endl;
|
||||
}
|
||||
|
||||
void DisplayMachineState( const BitMachine & bitMachine )
|
||||
{
|
||||
bitMachine.state_cast< const IDisplay & >().Display();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
boost::intrusive_ptr< const sc::event_base > pFlipBitEvents[ NO_OF_BITS ];
|
||||
|
||||
struct EventInserter
|
||||
{
|
||||
template< class BitNo >
|
||||
void operator()( const BitNo & )
|
||||
{
|
||||
pFlipBitEvents[ BitNo::value ] = new EvFlipBit< BitNo >();
|
||||
}
|
||||
};
|
||||
|
||||
void FillEventArray()
|
||||
{
|
||||
mpl::for_each< mpl::range_c< unsigned int, 0, NO_OF_BITS > >(
|
||||
EventInserter() );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
void VisitAllStates( BitMachine & bitMachine, unsigned int msb )
|
||||
{
|
||||
if ( msb > 0 )
|
||||
{
|
||||
VisitAllStates( bitMachine, msb - 1 );
|
||||
}
|
||||
|
||||
bitMachine.process_event( *pFlipBitEvents[ msb ] );
|
||||
DisplayMachineState( bitMachine );
|
||||
|
||||
if ( msb > 0 )
|
||||
{
|
||||
VisitAllStates( bitMachine, msb - 1 );
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
char GetKey()
|
||||
{
|
||||
char key;
|
||||
std::cin >> key;
|
||||
return key;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
int main()
|
||||
{
|
||||
FillEventArray< NO_OF_BITS >();
|
||||
FillEventArray();
|
||||
|
||||
const unsigned int noOfStates = 1 << NO_OF_BITS;
|
||||
std::cout << "Boost.Statechart BitMachine example\n";
|
||||
std::cout << "Machine configuration: " << noOfStates <<
|
||||
" states interconnected with " << noOfTransitions << " transitions.\n\n";
|
||||
" states interconnected with " << noOfStates * NO_OF_BITS <<
|
||||
" transitions.\n\n";
|
||||
|
||||
for ( unsigned int bit = 0; bit < NO_OF_BITS; ++bit )
|
||||
{
|
||||
@@ -304,7 +223,6 @@ int main()
|
||||
}
|
||||
|
||||
std::cout << "a<CR>: Goes through all states automatically\n";
|
||||
std::cout << "p<CR>: Performance test\n";
|
||||
std::cout << "e<CR>: Exits the program\n\n";
|
||||
std::cout << "You may chain commands, e.g. 31<CR> flips bits 3 and 1\n\n";
|
||||
|
||||
@@ -319,7 +237,6 @@ int main()
|
||||
if ( ( key >= '0' ) && ( key < static_cast< char >( '0' + NO_OF_BITS ) ) )
|
||||
{
|
||||
bitMachine.process_event( *pFlipBitEvents[ key - '0' ] );
|
||||
++eventsSentTotal;
|
||||
DisplayMachineState( bitMachine );
|
||||
}
|
||||
else
|
||||
@@ -328,28 +245,7 @@ int main()
|
||||
{
|
||||
case 'a':
|
||||
{
|
||||
VisitAllStates< NO_OF_BITS - 1, true >( bitMachine );
|
||||
}
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
{
|
||||
std::cout << "\nSending " << noOfEvents << " events. Please wait...\n";
|
||||
|
||||
const unsigned long startEvents2 = eventsSentTotal;
|
||||
const std::clock_t startTime2 = std::clock();
|
||||
|
||||
for ( unsigned int lap = 0; lap < noOfLaps; ++lap )
|
||||
{
|
||||
VisitAllStates< NO_OF_BITS - 1, false >( bitMachine );
|
||||
}
|
||||
|
||||
const std::clock_t elapsedTime2 = std::clock() - startTime2;
|
||||
const unsigned int eventsSent2 = eventsSentTotal - startEvents2;
|
||||
std::cout << "Time to dispatch one event and\n" <<
|
||||
"perform the resulting transition: ";
|
||||
std::cout << elapsedTime2 / static_cast< double >( CLOCKS_PER_SEC ) *
|
||||
1000000.0 / eventsSent2 << " microseconds\n\n";
|
||||
VisitAllStates( bitMachine, NO_OF_BITS - 1 );
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user