You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
445 lines
15 KiB
445 lines
15 KiB
#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
|
|
|