| #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::auto_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< 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 |