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