#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 #include #include #include #include #include #include #include #include #include // BOOST_INTEL #include #include #include #include // std::allocator, std::auto_ptr namespace boost { namespace statechart { namespace detail { template struct unwrap_impl { template< typename T > struct apply { typedef T type; }; }; template<> struct unwrap_impl { template< typename T > struct apply { typedef typename T::type & type; }; }; template 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< void > > class processor_container : noncopyable { typedef event_processor< Scheduler > processor_base_type; typedef std::auto_ptr< processor_base_type > processor_holder_type; 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 ); processor_holder_type holder( new Processor( context ) ); *pProcessor = holder; } template< class Processor, typename Arg1 > void create_processor_impl1( const processor_holder_ptr_type & pProcessor, const processor_context & context, Arg1 arg1 ) { processorSet_.insert( pProcessor ); processor_holder_type holder( new Processor( context, arg1 ) ); *pProcessor = holder; } 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 ); processor_holder_type holder( new Processor( context, arg1, arg2 ) ); *pProcessor = holder; } 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 ); processor_holder_type holder( new Processor( context, arg1, arg2, arg3 ) ); *pProcessor = holder; } 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 ); processor_holder_type holder( new Processor( context, arg1, arg2, arg3, arg4 ) ); *pProcessor = holder; } 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 ); processor_holder_type holder( new Processor( context, arg1, arg2, arg3, arg4, arg5 ) ); *pProcessor = holder; } 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 ); processor_holder_type holder( new Processor( context, arg1, arg2, arg3, arg4, arg5, arg6 ) ); *pProcessor = holder; } 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