Chris@16: #ifndef BOOST_STATECHART_PROCESSOR_CONTAINER_HPP_INCLUDED Chris@16: #define BOOST_STATECHART_PROCESSOR_CONTAINER_HPP_INCLUDED Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: // Copyright 2002-2008 Andreas Huber Doenni Chris@16: // Distributed under the Boost Software License, Version 1.0. (See accompany- Chris@16: // ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: Chris@16: Chris@16: Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include // BOOST_INTEL Chris@16: Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include // std::allocator, std::auto_ptr Chris@16: Chris@16: Chris@16: Chris@16: namespace boost Chris@16: { Chris@16: namespace statechart Chris@16: { Chris@16: namespace detail Chris@16: { Chris@16: template Chris@16: struct unwrap_impl Chris@16: { Chris@16: template< typename T > Chris@16: struct apply { typedef T type; }; Chris@16: }; Chris@16: Chris@16: template<> Chris@16: struct unwrap_impl Chris@16: { Chris@16: template< typename T > Chris@16: struct apply { typedef typename T::type & type; }; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct unwrap Chris@16: { Chris@16: typedef typename unwrap_impl< Chris@16: is_reference_wrapper< T >::value >::template apply< T >::type type; Chris@16: }; Chris@16: } Chris@16: Chris@16: Chris@16: template< Chris@16: class Scheduler, Chris@16: class WorkItem, Chris@16: class Allocator = std::allocator< void > > Chris@16: class processor_container : noncopyable Chris@16: { Chris@16: typedef event_processor< Scheduler > processor_base_type; Chris@16: typedef std::auto_ptr< processor_base_type > processor_holder_type; Chris@16: typedef shared_ptr< processor_holder_type > processor_holder_ptr_type; Chris@16: Chris@16: public: Chris@16: ////////////////////////////////////////////////////////////////////////// Chris@16: typedef weak_ptr< processor_holder_type > processor_handle; Chris@16: Chris@16: class processor_context Chris@16: { Chris@16: processor_context( Chris@16: Scheduler & scheduler, const processor_handle & handle Chris@16: ) : Chris@16: scheduler_( scheduler ), Chris@16: handle_( handle ) Chris@16: { Chris@16: } Chris@16: Chris@16: #if BOOST_WORKAROUND( BOOST_INTEL, BOOST_TESTED_AT( 800 ) ) Chris@16: public: Chris@16: // for some reason Intel 8.0 seems to think that the following functions Chris@16: // are inaccessible from event_processor<>::event_processor Chris@16: #endif Chris@16: Chris@16: Scheduler & my_scheduler() const { return scheduler_; } Chris@16: const processor_handle & my_handle() const { return handle_; } Chris@16: Chris@16: #if BOOST_WORKAROUND( BOOST_INTEL, BOOST_TESTED_AT( 800 ) ) Chris@16: private: Chris@16: #endif Chris@16: Chris@16: // avoids C4512 (assignment operator could not be generated) Chris@16: processor_context & operator=( const processor_context & ); Chris@16: Chris@16: Scheduler & scheduler_; Chris@16: const processor_handle handle_; Chris@16: Chris@16: friend class processor_container; Chris@16: friend class event_processor< Scheduler >; Chris@16: }; Chris@16: Chris@16: template< class Processor > Chris@16: WorkItem create_processor( processor_handle & handle, Scheduler & scheduler ) Chris@16: { Chris@16: processor_holder_ptr_type pProcessor = make_processor_holder(); Chris@16: handle = pProcessor; Chris@16: typedef void ( processor_container::*impl_fun_ptr )( Chris@16: const processor_holder_ptr_type &, const processor_context & ); Chris@16: impl_fun_ptr pImpl = Chris@16: &processor_container::template create_processor_impl0< Processor >; Chris@16: return WorkItem( Chris@16: boost::bind( pImpl, this, pProcessor, Chris@16: processor_context( scheduler, handle ) ), Chris@16: Allocator() ); Chris@16: } Chris@16: Chris@16: template< class Processor, typename Arg1 > Chris@16: WorkItem create_processor( Chris@16: processor_handle & handle, Scheduler & scheduler, Arg1 arg1 ) Chris@16: { Chris@16: processor_holder_ptr_type pProcessor = make_processor_holder(); Chris@16: handle = pProcessor; Chris@16: typedef typename detail::unwrap< Arg1 >::type arg1_type; Chris@16: typedef void ( processor_container::*impl_fun_ptr )( Chris@16: const processor_holder_ptr_type &, const processor_context &, Chris@16: arg1_type ); Chris@16: impl_fun_ptr pImpl = Chris@16: &processor_container::template create_processor_impl1< Chris@16: Processor, arg1_type >; Chris@16: return WorkItem( Chris@16: boost::bind( pImpl, this, pProcessor, processor_context( scheduler, handle ), Chris@16: arg1 ), Chris@16: Allocator() ); Chris@16: } Chris@16: Chris@16: template< class Processor, typename Arg1, typename Arg2 > Chris@16: WorkItem create_processor( Chris@16: processor_handle & handle, Scheduler & scheduler, Arg1 arg1, Arg2 arg2 ) Chris@16: { Chris@16: processor_holder_ptr_type pProcessor = make_processor_holder(); Chris@16: handle = pProcessor; Chris@16: typedef typename detail::unwrap< Arg1 >::type arg1_type; Chris@16: typedef typename detail::unwrap< Arg2 >::type arg2_type; Chris@16: typedef void ( processor_container::*impl_fun_ptr )( Chris@16: const processor_holder_ptr_type &, const processor_context &, Chris@16: arg1_type, arg2_type ); Chris@16: impl_fun_ptr pImpl = Chris@16: &processor_container::template create_processor_impl2< Chris@16: Processor, arg1_type, arg2_type >; Chris@16: return WorkItem( Chris@16: boost::bind( pImpl, this, pProcessor, processor_context( scheduler, handle ), Chris@16: arg1, arg2 ), Chris@16: Allocator() ); Chris@16: } Chris@16: Chris@16: template< class Processor, typename Arg1, typename Arg2, typename Arg3 > Chris@16: WorkItem create_processor( Chris@16: processor_handle & handle, Scheduler & scheduler, Chris@16: Arg1 arg1, Arg2 arg2, Arg3 arg3 ) Chris@16: { Chris@16: processor_holder_ptr_type pProcessor = make_processor_holder(); Chris@16: handle = pProcessor; Chris@16: typedef typename detail::unwrap< Arg1 >::type arg1_type; Chris@16: typedef typename detail::unwrap< Arg2 >::type arg2_type; Chris@16: typedef typename detail::unwrap< Arg3 >::type arg3_type; Chris@16: typedef void ( processor_container::*impl_fun_ptr )( Chris@16: const processor_holder_ptr_type &, const processor_context &, Chris@16: arg1_type, arg2_type, arg3_type ); Chris@16: impl_fun_ptr pImpl = Chris@16: &processor_container::template create_processor_impl3< Chris@16: Processor, arg1_type, arg2_type, arg3_type >; Chris@16: return WorkItem( Chris@16: boost::bind( pImpl, this, pProcessor, processor_context( scheduler, handle ), Chris@16: arg1, arg2, arg3 ), Chris@16: Allocator() ); Chris@16: } Chris@16: Chris@16: template< Chris@16: class Processor, typename Arg1, typename Arg2, Chris@16: typename Arg3, typename Arg4 > Chris@16: WorkItem create_processor( Chris@16: processor_handle & handle, Scheduler & scheduler, Chris@16: Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4 ) Chris@16: { Chris@16: processor_holder_ptr_type pProcessor = make_processor_holder(); Chris@16: handle = pProcessor; Chris@16: typedef typename detail::unwrap< Arg1 >::type arg1_type; Chris@16: typedef typename detail::unwrap< Arg2 >::type arg2_type; Chris@16: typedef typename detail::unwrap< Arg3 >::type arg3_type; Chris@16: typedef typename detail::unwrap< Arg4 >::type arg4_type; Chris@16: typedef void ( processor_container::*impl_fun_ptr )( Chris@16: const processor_holder_ptr_type &, const processor_context &, Chris@16: arg1_type, arg2_type, arg3_type, arg4_type ); Chris@16: impl_fun_ptr pImpl = Chris@16: &processor_container::template create_processor_impl4< Chris@16: Processor, arg1_type, arg2_type, arg3_type, arg4_type >; Chris@16: return WorkItem( Chris@16: boost::bind( pImpl, this, pProcessor, processor_context( scheduler, handle ), Chris@16: arg1, arg2, arg3, arg4 ), Chris@16: Allocator() ); Chris@16: } Chris@16: Chris@16: template< Chris@16: class Processor, typename Arg1, typename Arg2, Chris@16: typename Arg3, typename Arg4, typename Arg5 > Chris@16: WorkItem create_processor( Chris@16: processor_handle & handle, Scheduler & scheduler, Chris@16: Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5 ) Chris@16: { Chris@16: processor_holder_ptr_type pProcessor = make_processor_holder(); Chris@16: handle = pProcessor; Chris@16: typedef typename detail::unwrap< Arg1 >::type arg1_type; Chris@16: typedef typename detail::unwrap< Arg2 >::type arg2_type; Chris@16: typedef typename detail::unwrap< Arg3 >::type arg3_type; Chris@16: typedef typename detail::unwrap< Arg4 >::type arg4_type; Chris@16: typedef typename detail::unwrap< Arg5 >::type arg5_type; Chris@16: typedef void ( processor_container::*impl_fun_ptr )( Chris@16: const processor_holder_ptr_type &, const processor_context &, Chris@16: arg1_type, arg2_type, arg3_type, arg4_type, arg5_type ); Chris@16: impl_fun_ptr pImpl = Chris@16: &processor_container::template create_processor_impl5< Chris@16: Processor, arg1_type, arg2_type, arg3_type, arg4_type, arg5_type >; Chris@16: return WorkItem( Chris@16: boost::bind( pImpl, this, pProcessor, processor_context( scheduler, handle ), Chris@16: arg1, arg2, arg3, arg4, arg5 ), Chris@16: Allocator() ); Chris@16: } Chris@16: Chris@16: template< Chris@16: class Processor, typename Arg1, typename Arg2, Chris@16: typename Arg3, typename Arg4, typename Arg5, typename Arg6 > Chris@16: WorkItem create_processor( Chris@16: processor_handle & handle, Scheduler & scheduler, Chris@16: Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5, Arg6 arg6 ) Chris@16: { Chris@16: processor_holder_ptr_type pProcessor = make_processor_holder(); Chris@16: handle = pProcessor; Chris@16: typedef typename detail::unwrap< Arg1 >::type arg1_type; Chris@16: typedef typename detail::unwrap< Arg2 >::type arg2_type; Chris@16: typedef typename detail::unwrap< Arg3 >::type arg3_type; Chris@16: typedef typename detail::unwrap< Arg4 >::type arg4_type; Chris@16: typedef typename detail::unwrap< Arg5 >::type arg5_type; Chris@16: typedef typename detail::unwrap< Arg6 >::type arg6_type; Chris@16: typedef void ( processor_container::*impl_fun_ptr )( Chris@16: const processor_holder_ptr_type &, const processor_context &, Chris@16: arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, arg6_type ); Chris@16: impl_fun_ptr pImpl = Chris@16: &processor_container::template create_processor_impl6< Chris@16: Processor, Chris@16: arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, arg6_type >; Chris@16: return WorkItem( Chris@16: boost::bind( pImpl, this, pProcessor, processor_context( scheduler, handle ), Chris@16: arg1, arg2, arg3, arg4, arg5, arg6 ), Chris@16: Allocator() ); Chris@16: } Chris@16: Chris@16: WorkItem destroy_processor( const processor_handle & processor ) Chris@16: { Chris@16: return WorkItem( Chris@16: boost::bind( &processor_container::destroy_processor_impl, this, processor ), Chris@16: Allocator() ); Chris@16: } Chris@16: Chris@16: WorkItem initiate_processor( const processor_handle & processor ) Chris@16: { Chris@16: return WorkItem( Chris@16: boost::bind( &processor_container::initiate_processor_impl, this, Chris@16: processor ), Chris@16: Allocator() ); Chris@16: } Chris@16: Chris@16: WorkItem terminate_processor( const processor_handle & processor ) Chris@16: { Chris@16: return WorkItem( Chris@16: boost::bind( &processor_container::terminate_processor_impl, this, Chris@16: processor ), Chris@16: Allocator() ); Chris@16: } Chris@16: Chris@16: typedef intrusive_ptr< const event_base > event_ptr_type; Chris@16: Chris@16: WorkItem queue_event( Chris@16: const processor_handle & processor, const event_ptr_type & pEvent ) Chris@16: { Chris@16: BOOST_ASSERT( pEvent.get() != 0 ); Chris@16: Chris@16: return WorkItem( Chris@16: boost::bind( &processor_container::queue_event_impl, this, processor, Chris@16: pEvent ), Chris@16: Allocator() ); Chris@16: } Chris@16: Chris@16: private: Chris@16: ////////////////////////////////////////////////////////////////////////// Chris@16: processor_holder_ptr_type make_processor_holder() Chris@16: { Chris@16: return processor_holder_ptr_type( new processor_holder_type() ); Chris@16: } Chris@16: Chris@16: template< class Processor > Chris@16: void create_processor_impl0( Chris@16: const processor_holder_ptr_type & pProcessor, Chris@16: const processor_context & context ) Chris@16: { Chris@16: processorSet_.insert( pProcessor ); Chris@16: processor_holder_type holder( new Processor( context ) ); Chris@16: *pProcessor = holder; Chris@16: } Chris@16: Chris@16: template< class Processor, typename Arg1 > Chris@16: void create_processor_impl1( Chris@16: const processor_holder_ptr_type & pProcessor, Chris@16: const processor_context & context, Arg1 arg1 ) Chris@16: { Chris@16: processorSet_.insert( pProcessor ); Chris@16: processor_holder_type holder( new Processor( context, arg1 ) ); Chris@16: *pProcessor = holder; Chris@16: } Chris@16: Chris@16: template< class Processor, typename Arg1, typename Arg2 > Chris@16: void create_processor_impl2( Chris@16: const processor_holder_ptr_type & pProcessor, Chris@16: const processor_context & context, Arg1 arg1, Arg2 arg2 ) Chris@16: { Chris@16: processorSet_.insert( pProcessor ); Chris@16: processor_holder_type holder( new Processor( context, arg1, arg2 ) ); Chris@16: *pProcessor = holder; Chris@16: } Chris@16: Chris@16: template< class Processor, typename Arg1, typename Arg2, typename Arg3 > Chris@16: void create_processor_impl3( Chris@16: const processor_holder_ptr_type & pProcessor, Chris@16: const processor_context & context, Arg1 arg1, Arg2 arg2, Arg3 arg3 ) Chris@16: { Chris@16: processorSet_.insert( pProcessor ); Chris@16: processor_holder_type holder( Chris@16: new Processor( context, arg1, arg2, arg3 ) ); Chris@16: *pProcessor = holder; Chris@16: } Chris@16: Chris@16: template< Chris@16: class Processor, typename Arg1, typename Arg2, Chris@16: typename Arg3, typename Arg4 > Chris@16: void create_processor_impl4( Chris@16: const processor_holder_ptr_type & pProcessor, Chris@16: const processor_context & context, Chris@16: Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4 ) Chris@16: { Chris@16: processorSet_.insert( pProcessor ); Chris@16: processor_holder_type holder( Chris@16: new Processor( context, arg1, arg2, arg3, arg4 ) ); Chris@16: *pProcessor = holder; Chris@16: } Chris@16: Chris@16: template< Chris@16: class Processor, typename Arg1, typename Arg2, Chris@16: typename Arg3, typename Arg4, typename Arg5 > Chris@16: void create_processor_impl5( Chris@16: const processor_holder_ptr_type & pProcessor, Chris@16: const processor_context & context, Chris@16: Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5 ) Chris@16: { Chris@16: processorSet_.insert( pProcessor ); Chris@16: processor_holder_type holder( Chris@16: new Processor( context, arg1, arg2, arg3, arg4, arg5 ) ); Chris@16: *pProcessor = holder; Chris@16: } Chris@16: Chris@16: template< Chris@16: class Processor, typename Arg1, typename Arg2, Chris@16: typename Arg3, typename Arg4, typename Arg5, typename Arg6 > Chris@16: void create_processor_impl6( Chris@16: const processor_holder_ptr_type & pProcessor, Chris@16: const processor_context & context, Chris@16: Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5, Arg6 arg6 ) Chris@16: { Chris@16: processorSet_.insert( pProcessor ); Chris@16: processor_holder_type holder( Chris@16: new Processor( context, arg1, arg2, arg3, arg4, arg5, arg6 ) ); Chris@16: *pProcessor = holder; Chris@16: } Chris@16: Chris@16: void destroy_processor_impl( const processor_handle & processor ) Chris@16: { Chris@16: const processor_holder_ptr_type pProcessor = processor.lock(); Chris@16: Chris@16: if ( pProcessor != 0 ) Chris@16: { Chris@16: processorSet_.erase( pProcessor ); Chris@16: } Chris@16: } Chris@16: Chris@16: void initiate_processor_impl( const processor_handle & processor ) Chris@16: { Chris@16: const processor_holder_ptr_type pProcessor = processor.lock(); Chris@16: Chris@16: if ( pProcessor != 0 ) Chris@16: { Chris@16: ( *pProcessor )->initiate(); Chris@16: } Chris@16: } Chris@16: Chris@16: void terminate_processor_impl( const processor_handle & processor ) Chris@16: { Chris@16: const processor_holder_ptr_type pProcessor = processor.lock(); Chris@16: Chris@16: if ( pProcessor != 0 ) Chris@16: { Chris@16: ( *pProcessor )->terminate(); Chris@16: } Chris@16: } Chris@16: Chris@16: void queue_event_impl( Chris@16: const processor_handle & processor, const event_ptr_type & pEvent ) Chris@16: { Chris@16: const processor_holder_ptr_type pProcessor = processor.lock(); Chris@16: Chris@16: if ( pProcessor != 0 ) Chris@16: { Chris@16: ( *pProcessor )->process_event( *pEvent ); Chris@16: } Chris@16: } Chris@16: Chris@16: typedef std::set< Chris@16: processor_holder_ptr_type, Chris@16: std::less< processor_holder_ptr_type >, Chris@16: typename boost::detail::allocator::rebind_to< Chris@16: Allocator, processor_holder_ptr_type >::type Chris@16: > event_processor_set_type; Chris@16: Chris@16: event_processor_set_type processorSet_; Chris@16: }; Chris@16: Chris@16: Chris@16: } // namespace statechart Chris@16: } // namespace boost Chris@16: Chris@16: Chris@16: Chris@16: #endif