123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438 |
- #ifndef BOOST_STATECHART_PROCESSOR_CONTAINER_HPP_INCLUDED
- #define BOOST_STATECHART_PROCESSOR_CONTAINER_HPP_INCLUDED
- //////////////////////////////////////////////////////////////////////////////
- // Copyright 2002-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/statechart/event_base.hpp>
- #include <boost/statechart/event_processor.hpp>
- #include <boost/assert.hpp>
- #include <boost/ref.hpp>
- #include <boost/noncopyable.hpp>
- #include <boost/intrusive_ptr.hpp>
- #include <boost/shared_ptr.hpp>
- #include <boost/weak_ptr.hpp>
- #include <boost/bind.hpp>
- #include <boost/config.hpp> // BOOST_INTEL
- #include <boost/detail/workaround.hpp>
- #include <boost/detail/allocator_utilities.hpp>
- #include <set>
- #include <memory> // std::allocator, std::unique_ptr
- namespace boost
- {
- namespace statechart
- {
- namespace detail
- {
- template<bool IsReferenceWrapper>
- struct unwrap_impl
- {
- template< typename T >
- struct apply { typedef T type; };
- };
- template<>
- struct unwrap_impl<true>
- {
- template< typename T >
- struct apply { typedef typename T::type & type; };
- };
- template<typename T>
- struct unwrap
- {
- typedef typename unwrap_impl<
- is_reference_wrapper< T >::value >::template apply< T >::type type;
- };
- }
- template<
- class Scheduler,
- class WorkItem,
- class Allocator = std::allocator< none > >
- class processor_container : noncopyable
- {
- typedef event_processor< Scheduler > processor_base_type;
- #ifdef BOOST_NO_AUTO_PTR
- typedef std::unique_ptr< processor_base_type > processor_holder_type;
- #else
- typedef std::auto_ptr< processor_base_type > processor_holder_type;
- #endif
- typedef shared_ptr< processor_holder_type > processor_holder_ptr_type;
- public:
- //////////////////////////////////////////////////////////////////////////
- typedef weak_ptr< processor_holder_type > processor_handle;
- class processor_context
- {
- processor_context(
- Scheduler & scheduler, const processor_handle & handle
- ) :
- scheduler_( scheduler ),
- handle_( handle )
- {
- }
- #if BOOST_WORKAROUND( BOOST_INTEL, BOOST_TESTED_AT( 800 ) )
- public:
- // for some reason Intel 8.0 seems to think that the following functions
- // are inaccessible from event_processor<>::event_processor
- #endif
- Scheduler & my_scheduler() const { return scheduler_; }
- const processor_handle & my_handle() const { return handle_; }
- #if BOOST_WORKAROUND( BOOST_INTEL, BOOST_TESTED_AT( 800 ) )
- private:
- #endif
- // avoids C4512 (assignment operator could not be generated)
- processor_context & operator=( const processor_context & );
- Scheduler & scheduler_;
- const processor_handle handle_;
- friend class processor_container;
- friend class event_processor< Scheduler >;
- };
- template< class Processor >
- WorkItem create_processor( processor_handle & handle, Scheduler & scheduler )
- {
- processor_holder_ptr_type pProcessor = make_processor_holder();
- handle = pProcessor;
- typedef void ( processor_container::*impl_fun_ptr )(
- const processor_holder_ptr_type &, const processor_context & );
- impl_fun_ptr pImpl =
- &processor_container::template create_processor_impl0< Processor >;
- return WorkItem(
- boost::bind( pImpl, this, pProcessor,
- processor_context( scheduler, handle ) ),
- Allocator() );
- }
- template< class Processor, typename Arg1 >
- WorkItem create_processor(
- processor_handle & handle, Scheduler & scheduler, Arg1 arg1 )
- {
- processor_holder_ptr_type pProcessor = make_processor_holder();
- handle = pProcessor;
- typedef typename detail::unwrap< Arg1 >::type arg1_type;
- typedef void ( processor_container::*impl_fun_ptr )(
- const processor_holder_ptr_type &, const processor_context &,
- arg1_type );
- impl_fun_ptr pImpl =
- &processor_container::template create_processor_impl1<
- Processor, arg1_type >;
- return WorkItem(
- boost::bind( pImpl, this, pProcessor, processor_context( scheduler, handle ),
- arg1 ),
- Allocator() );
- }
- template< class Processor, typename Arg1, typename Arg2 >
- WorkItem create_processor(
- processor_handle & handle, Scheduler & scheduler, Arg1 arg1, Arg2 arg2 )
- {
- processor_holder_ptr_type pProcessor = make_processor_holder();
- handle = pProcessor;
- typedef typename detail::unwrap< Arg1 >::type arg1_type;
- typedef typename detail::unwrap< Arg2 >::type arg2_type;
- typedef void ( processor_container::*impl_fun_ptr )(
- const processor_holder_ptr_type &, const processor_context &,
- arg1_type, arg2_type );
- impl_fun_ptr pImpl =
- &processor_container::template create_processor_impl2<
- Processor, arg1_type, arg2_type >;
- return WorkItem(
- boost::bind( pImpl, this, pProcessor, processor_context( scheduler, handle ),
- arg1, arg2 ),
- Allocator() );
- }
- template< class Processor, typename Arg1, typename Arg2, typename Arg3 >
- WorkItem create_processor(
- processor_handle & handle, Scheduler & scheduler,
- Arg1 arg1, Arg2 arg2, Arg3 arg3 )
- {
- processor_holder_ptr_type pProcessor = make_processor_holder();
- handle = pProcessor;
- typedef typename detail::unwrap< Arg1 >::type arg1_type;
- typedef typename detail::unwrap< Arg2 >::type arg2_type;
- typedef typename detail::unwrap< Arg3 >::type arg3_type;
- typedef void ( processor_container::*impl_fun_ptr )(
- const processor_holder_ptr_type &, const processor_context &,
- arg1_type, arg2_type, arg3_type );
- impl_fun_ptr pImpl =
- &processor_container::template create_processor_impl3<
- Processor, arg1_type, arg2_type, arg3_type >;
- return WorkItem(
- boost::bind( pImpl, this, pProcessor, processor_context( scheduler, handle ),
- arg1, arg2, arg3 ),
- Allocator() );
- }
- template<
- class Processor, typename Arg1, typename Arg2,
- typename Arg3, typename Arg4 >
- WorkItem create_processor(
- processor_handle & handle, Scheduler & scheduler,
- Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4 )
- {
- processor_holder_ptr_type pProcessor = make_processor_holder();
- handle = pProcessor;
- typedef typename detail::unwrap< Arg1 >::type arg1_type;
- typedef typename detail::unwrap< Arg2 >::type arg2_type;
- typedef typename detail::unwrap< Arg3 >::type arg3_type;
- typedef typename detail::unwrap< Arg4 >::type arg4_type;
- typedef void ( processor_container::*impl_fun_ptr )(
- const processor_holder_ptr_type &, const processor_context &,
- arg1_type, arg2_type, arg3_type, arg4_type );
- impl_fun_ptr pImpl =
- &processor_container::template create_processor_impl4<
- Processor, arg1_type, arg2_type, arg3_type, arg4_type >;
- return WorkItem(
- boost::bind( pImpl, this, pProcessor, processor_context( scheduler, handle ),
- arg1, arg2, arg3, arg4 ),
- Allocator() );
- }
- template<
- class Processor, typename Arg1, typename Arg2,
- typename Arg3, typename Arg4, typename Arg5 >
- WorkItem create_processor(
- processor_handle & handle, Scheduler & scheduler,
- Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5 )
- {
- processor_holder_ptr_type pProcessor = make_processor_holder();
- handle = pProcessor;
- typedef typename detail::unwrap< Arg1 >::type arg1_type;
- typedef typename detail::unwrap< Arg2 >::type arg2_type;
- typedef typename detail::unwrap< Arg3 >::type arg3_type;
- typedef typename detail::unwrap< Arg4 >::type arg4_type;
- typedef typename detail::unwrap< Arg5 >::type arg5_type;
- typedef void ( processor_container::*impl_fun_ptr )(
- const processor_holder_ptr_type &, const processor_context &,
- arg1_type, arg2_type, arg3_type, arg4_type, arg5_type );
- impl_fun_ptr pImpl =
- &processor_container::template create_processor_impl5<
- Processor, arg1_type, arg2_type, arg3_type, arg4_type, arg5_type >;
- return WorkItem(
- boost::bind( pImpl, this, pProcessor, processor_context( scheduler, handle ),
- arg1, arg2, arg3, arg4, arg5 ),
- Allocator() );
- }
- template<
- class Processor, typename Arg1, typename Arg2,
- typename Arg3, typename Arg4, typename Arg5, typename Arg6 >
- WorkItem create_processor(
- processor_handle & handle, Scheduler & scheduler,
- Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5, Arg6 arg6 )
- {
- processor_holder_ptr_type pProcessor = make_processor_holder();
- handle = pProcessor;
- typedef typename detail::unwrap< Arg1 >::type arg1_type;
- typedef typename detail::unwrap< Arg2 >::type arg2_type;
- typedef typename detail::unwrap< Arg3 >::type arg3_type;
- typedef typename detail::unwrap< Arg4 >::type arg4_type;
- typedef typename detail::unwrap< Arg5 >::type arg5_type;
- typedef typename detail::unwrap< Arg6 >::type arg6_type;
- typedef void ( processor_container::*impl_fun_ptr )(
- const processor_holder_ptr_type &, const processor_context &,
- arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, arg6_type );
- impl_fun_ptr pImpl =
- &processor_container::template create_processor_impl6<
- Processor,
- arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, arg6_type >;
- return WorkItem(
- boost::bind( pImpl, this, pProcessor, processor_context( scheduler, handle ),
- arg1, arg2, arg3, arg4, arg5, arg6 ),
- Allocator() );
- }
- WorkItem destroy_processor( const processor_handle & processor )
- {
- return WorkItem(
- boost::bind( &processor_container::destroy_processor_impl, this, processor ),
- Allocator() );
- }
- WorkItem initiate_processor( const processor_handle & processor )
- {
- return WorkItem(
- boost::bind( &processor_container::initiate_processor_impl, this,
- processor ),
- Allocator() );
- }
- WorkItem terminate_processor( const processor_handle & processor )
- {
- return WorkItem(
- boost::bind( &processor_container::terminate_processor_impl, this,
- processor ),
- Allocator() );
- }
- typedef intrusive_ptr< const event_base > event_ptr_type;
- WorkItem queue_event(
- const processor_handle & processor, const event_ptr_type & pEvent )
- {
- BOOST_ASSERT( pEvent.get() != 0 );
- return WorkItem(
- boost::bind( &processor_container::queue_event_impl, this, processor,
- pEvent ),
- Allocator() );
- }
- private:
- //////////////////////////////////////////////////////////////////////////
- processor_holder_ptr_type make_processor_holder()
- {
- return processor_holder_ptr_type( new processor_holder_type() );
- }
- template< class Processor >
- void create_processor_impl0(
- const processor_holder_ptr_type & pProcessor,
- const processor_context & context )
- {
- processorSet_.insert( pProcessor );
- *pProcessor = processor_holder_type( new Processor( context ) );
- }
- template< class Processor, typename Arg1 >
- void create_processor_impl1(
- const processor_holder_ptr_type & pProcessor,
- const processor_context & context, Arg1 arg1 )
- {
- processorSet_.insert( pProcessor );
- *pProcessor = processor_holder_type( new Processor( context, arg1 ) );
- }
- template< class Processor, typename Arg1, typename Arg2 >
- void create_processor_impl2(
- const processor_holder_ptr_type & pProcessor,
- const processor_context & context, Arg1 arg1, Arg2 arg2 )
- {
- processorSet_.insert( pProcessor );
- *pProcessor = processor_holder_type( new Processor( context, arg1, arg2 ) );
- }
- template< class Processor, typename Arg1, typename Arg2, typename Arg3 >
- void create_processor_impl3(
- const processor_holder_ptr_type & pProcessor,
- const processor_context & context, Arg1 arg1, Arg2 arg2, Arg3 arg3 )
- {
- processorSet_.insert( pProcessor );
- *pProcessor = processor_holder_type( new Processor( context, arg1, arg2, arg3 ) );
- }
- template<
- class Processor, typename Arg1, typename Arg2,
- typename Arg3, typename Arg4 >
- void create_processor_impl4(
- const processor_holder_ptr_type & pProcessor,
- const processor_context & context,
- Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4 )
- {
- processorSet_.insert( pProcessor );
- *pProcessor = processor_holder_type( new Processor( context, arg1, arg2, arg3, arg4 ) );
- }
- template<
- class Processor, typename Arg1, typename Arg2,
- typename Arg3, typename Arg4, typename Arg5 >
- void create_processor_impl5(
- const processor_holder_ptr_type & pProcessor,
- const processor_context & context,
- Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5 )
- {
- processorSet_.insert( pProcessor );
- *pProcessor = processor_holder_type( new Processor( context, arg1, arg2, arg3, arg4, arg5 ) );
- }
- template<
- class Processor, typename Arg1, typename Arg2,
- typename Arg3, typename Arg4, typename Arg5, typename Arg6 >
- void create_processor_impl6(
- const processor_holder_ptr_type & pProcessor,
- const processor_context & context,
- Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5, Arg6 arg6 )
- {
- processorSet_.insert( pProcessor );
- *pProcessor = processor_holder_type( new Processor( context, arg1, arg2, arg3, arg4, arg5, arg6 ) );
- }
- void destroy_processor_impl( const processor_handle & processor )
- {
- const processor_holder_ptr_type pProcessor = processor.lock();
- if ( pProcessor != 0 )
- {
- processorSet_.erase( pProcessor );
- }
- }
- void initiate_processor_impl( const processor_handle & processor )
- {
- const processor_holder_ptr_type pProcessor = processor.lock();
- if ( pProcessor != 0 )
- {
- ( *pProcessor )->initiate();
- }
- }
- void terminate_processor_impl( const processor_handle & processor )
- {
- const processor_holder_ptr_type pProcessor = processor.lock();
- if ( pProcessor != 0 )
- {
- ( *pProcessor )->terminate();
- }
- }
- void queue_event_impl(
- const processor_handle & processor, const event_ptr_type & pEvent )
- {
- const processor_holder_ptr_type pProcessor = processor.lock();
- if ( pProcessor != 0 )
- {
- ( *pProcessor )->process_event( *pEvent );
- }
- }
- typedef std::set<
- processor_holder_ptr_type,
- std::less< processor_holder_ptr_type >,
- typename boost::detail::allocator::rebind_to<
- Allocator, processor_holder_ptr_type >::type
- > event_processor_set_type;
- event_processor_set_type processorSet_;
- };
- } // namespace statechart
- } // namespace boost
- #endif
|