123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326 |
- //////////////////////////////////////////////////////////////////////////////
- // Copyright 2005-2008 Andreas Huber Doenni
- // Distributed under the Boost Software License, Version 1.0. (See accompany-
- // ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- //////////////////////////////////////////////////////////////////////////////
- #include <boost/test/test_tools.hpp>
- #include <boost/statechart/asynchronous_state_machine.hpp>
- #include <boost/statechart/fifo_scheduler.hpp>
- #include <boost/statechart/event.hpp>
- #include <boost/statechart/simple_state.hpp>
- #include <boost/statechart/termination.hpp>
- #include <boost/statechart/custom_reaction.hpp>
- #include <boost/mpl/list.hpp>
- #include <boost/bind.hpp>
- #include <boost/ref.hpp>
- #include <stdexcept>
- namespace sc = boost::statechart;
- namespace mpl = boost::mpl;
- struct EvCheckCtorArgs : sc::event< EvCheckCtorArgs >
- {
- public:
- EvCheckCtorArgs( int expectedArgs ) : expectedArgs_( expectedArgs ) {}
- const int expectedArgs_;
- private:
- // avoids C4512 (assignment operator could not be generated)
- EvCheckCtorArgs & operator=( const EvCheckCtorArgs & );
- };
- struct EvTerminate : sc::event< EvTerminate > {};
- struct EvFail : sc::event< EvFail > {};
- struct Initial;
- struct FifoSchedulerTest :
- sc::asynchronous_state_machine< FifoSchedulerTest, Initial >
- {
- public:
- //////////////////////////////////////////////////////////////////////////
- FifoSchedulerTest( my_context ctx ) :
- my_base( ctx ),
- ctorArgs_( 0 )
- {
- }
- FifoSchedulerTest( my_context ctx, int arg1 ) :
- my_base( ctx ),
- ctorArgs_( arg1 )
- {
- }
- FifoSchedulerTest( my_context ctx, int arg1, int arg2 ) :
- my_base( ctx ),
- ctorArgs_( arg1 * 10 + arg2 )
- {
- }
- FifoSchedulerTest( my_context ctx, int arg1, int arg2, int arg3 ) :
- my_base( ctx ),
- ctorArgs_( ( arg1 * 10 + arg2 ) * 10 + arg3 )
- {
- }
- FifoSchedulerTest(
- my_context ctx,
- int arg1, int arg2, int arg3, int arg4
- ) :
- my_base( ctx ),
- ctorArgs_( ( ( arg1 * 10 + arg2 ) * 10 + arg3 ) * 10 + arg4 )
- {
- }
- FifoSchedulerTest(
- my_context ctx,
- int arg1, int arg2, int arg3, int arg4, int arg5
- ) :
- my_base( ctx ),
- ctorArgs_( ( ( ( arg1 * 10 + arg2 ) * 10 +
- arg3 ) * 10 + arg4 ) * 10 + arg5 )
- {
- }
- FifoSchedulerTest(
- my_context ctx,
- int arg1, int arg2, int arg3, int arg4, int arg5, int arg6
- ) :
- my_base( ctx ),
- ctorArgs_( ( ( ( ( arg1 * 10 + arg2 ) * 10 +
- arg3 ) * 10 + arg4 ) * 10 + arg5 ) * 10 + arg6 )
- {
- }
- int CtorArgs()
- {
- return ctorArgs_;
- }
- private:
- //////////////////////////////////////////////////////////////////////////
- const int ctorArgs_;
- };
- boost::intrusive_ptr< const sc::event_base > MakeEvent(
- const sc::event_base * pEvent )
- {
- return boost::intrusive_ptr< const sc::event_base >( pEvent );
- }
- struct Initial : sc::simple_state< Initial, FifoSchedulerTest >
- {
- typedef mpl::list<
- sc::custom_reaction< EvCheckCtorArgs >,
- sc::termination< EvTerminate >,
- sc::custom_reaction< EvFail >
- > reactions;
- sc::result react( const EvCheckCtorArgs & ev )
- {
- BOOST_REQUIRE( ev.expectedArgs_ == outermost_context().CtorArgs() );
- outermost_context_type & machine = outermost_context();
- machine.my_scheduler().queue_event(
- machine.my_handle(), MakeEvent( new EvTerminate() ) );
- return discard_event();
- }
- sc::result react( const EvFail & )
- {
- BOOST_FAIL( "State machine is unexpectedly still running." );
- return discard_event();
- }
- };
- struct UnexpectedEventCount : public std::runtime_error
- {
- UnexpectedEventCount() : std::runtime_error( "" ) {}
- };
- void RunScheduler(
- sc::fifo_scheduler<> & scheduler, unsigned long expectedEventCount )
- {
- // Workaround: For some reason MSVC has a problem with BOOST_REQUIRE here
- // (C1055: compiler limit: out of keys)
- if ( scheduler() != expectedEventCount )
- {
- throw UnexpectedEventCount();
- }
- }
- static int refArg1;
- static int refArg2;
- static int refArg3;
- static int refArg4;
- static int refArg5;
- static int refArg6;
- void Check(
- sc::fifo_scheduler<> & scheduler,
- const sc::fifo_scheduler<>::processor_handle & processor,
- int ctorArgs )
- {
- refArg1 = 6;
- refArg2 = 5;
- refArg3 = 4;
- refArg4 = 3;
- refArg5 = 2;
- refArg6 = 1;
- // Make sure the processor has been created
- RunScheduler( scheduler, 1UL );
- refArg1 = refArg2 = refArg3 = refArg4 = refArg5 = refArg6 = 0;
- scheduler.initiate_processor( processor );
- // This event triggers the queueing of another event, which itself
- // terminates the machine ...
- scheduler.queue_event(
- processor, MakeEvent( new EvCheckCtorArgs( ctorArgs ) ) );
- // ... that's why 3 instead of two events must have been processed
- RunScheduler( scheduler, 3UL );
- // Since the machine has been terminated, this event will be ignored
- scheduler.queue_event( processor, MakeEvent( new EvFail() ) );
- RunScheduler( scheduler, 1UL );
- // Check that we can reinitiate the machine
- scheduler.initiate_processor( processor );
- scheduler.queue_event(
- processor, MakeEvent( new EvCheckCtorArgs( ctorArgs ) ) );
- RunScheduler( scheduler, 3UL );
- // Check that we are terminated again
- scheduler.queue_event( processor, MakeEvent( new EvFail() ) );
- RunScheduler( scheduler, 1UL );
- scheduler.destroy_processor( processor );
- // The following will simply be ignored because the processor has already
- // be destroyed
- scheduler.initiate_processor( processor );
- scheduler.queue_event(
- processor, MakeEvent( new EvCheckCtorArgs( ctorArgs ) ) );
- RunScheduler( scheduler, 3UL );
- }
- void SetToTrue( bool & value )
- {
- value = true;
- }
- int test_main( int, char* [] )
- {
- try
- {
- sc::fifo_scheduler<> scheduler;
- Check( scheduler, scheduler.create_processor< FifoSchedulerTest >(), 0 );
- Check(
- scheduler, scheduler.create_processor< FifoSchedulerTest >( 1 ), 1 );
- Check(
- scheduler,
- scheduler.create_processor< FifoSchedulerTest >(
- boost::cref( refArg1 ) ),
- 6 );
- Check(
- scheduler,
- scheduler.create_processor< FifoSchedulerTest >( 1, 2 ),
- 12 );
- Check(
- scheduler,
- scheduler.create_processor< FifoSchedulerTest >(
- boost::cref( refArg1 ), boost::cref( refArg2 ) ),
- 65 );
- Check(
- scheduler,
- scheduler.create_processor< FifoSchedulerTest >( 1, 2, 3 ),
- 123 );
- Check(
- scheduler,
- scheduler.create_processor< FifoSchedulerTest >(
- boost::cref( refArg1 ), boost::cref( refArg2 ),
- boost::cref( refArg3 ) ),
- 654 );
- Check(
- scheduler,
- scheduler.create_processor< FifoSchedulerTest >( 1, 2, 3, 4 ),
- 1234 );
- Check(
- scheduler,
- scheduler.create_processor< FifoSchedulerTest >(
- boost::cref( refArg1 ), boost::cref( refArg2 ),
- boost::cref( refArg3 ), boost::cref( refArg4 ) ),
- 6543 );
- Check(
- scheduler,
- scheduler.create_processor< FifoSchedulerTest >( 1, 2, 3, 4, 5 ),
- 12345 );
- Check(
- scheduler,
- scheduler.create_processor< FifoSchedulerTest >(
- boost::cref( refArg1 ), boost::cref( refArg2 ),
- boost::cref( refArg3 ), boost::cref( refArg4 ),
- boost::cref( refArg5 ) ),
- 65432 );
- Check(
- scheduler,
- scheduler.create_processor< FifoSchedulerTest >( 1, 2, 3, 4, 5, 6 ),
- 123456 );
- Check(
- scheduler,
- scheduler.create_processor< FifoSchedulerTest >(
- boost::cref( refArg1 ), boost::cref( refArg2 ),
- boost::cref( refArg3 ), boost::cref( refArg4 ),
- boost::cref( refArg5 ), boost::cref( refArg6 ) ),
- 654321 );
- RunScheduler( scheduler, 0UL );
- bool workItem1Processed = false;
- scheduler.queue_work_item(
- boost::bind( &SetToTrue, boost::ref( workItem1Processed ) ) );
- RunScheduler( scheduler, 1UL );
- BOOST_REQUIRE( workItem1Processed );
- scheduler.terminate();
- RunScheduler( scheduler, 1UL );
- BOOST_REQUIRE( scheduler.terminated() );
- RunScheduler( scheduler, 0UL );
- bool workItem2Processed = false;
- scheduler.queue_work_item(
- boost::bind( &SetToTrue, boost::ref( workItem2Processed ) ) );
- // After being terminated, a call to operator() must not process any more
- // events
- RunScheduler( scheduler, 0UL );
- BOOST_REQUIRE( !workItem2Processed );
- }
- catch ( const UnexpectedEventCount & )
- {
- BOOST_FAIL( "Unexpected event count." );
- }
- return 0;
- }
|