File indexing completed on 2025-01-18 09:52:32
0001 #ifndef BOOST_STATECHART_PROCESSOR_CONTAINER_HPP_INCLUDED
0002 #define BOOST_STATECHART_PROCESSOR_CONTAINER_HPP_INCLUDED
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <boost/statechart/event_base.hpp>
0012 #include <boost/statechart/event_processor.hpp>
0013
0014 #include <boost/assert.hpp>
0015 #include <boost/ref.hpp>
0016 #include <boost/noncopyable.hpp>
0017 #include <boost/intrusive_ptr.hpp>
0018 #include <boost/shared_ptr.hpp>
0019 #include <boost/weak_ptr.hpp>
0020 #include <boost/bind.hpp>
0021 #include <boost/config.hpp> // BOOST_INTEL
0022
0023 #include <boost/detail/workaround.hpp>
0024 #include <boost/detail/allocator_utilities.hpp>
0025
0026 #include <set>
0027 #include <memory> // std::allocator, std::unique_ptr
0028
0029
0030
0031 namespace boost
0032 {
0033 namespace statechart
0034 {
0035 namespace detail
0036 {
0037 template<bool IsReferenceWrapper>
0038 struct unwrap_impl
0039 {
0040 template< typename T >
0041 struct apply { typedef T type; };
0042 };
0043
0044 template<>
0045 struct unwrap_impl<true>
0046 {
0047 template< typename T >
0048 struct apply { typedef typename T::type & type; };
0049 };
0050
0051 template<typename T>
0052 struct unwrap
0053 {
0054 typedef typename unwrap_impl<
0055 is_reference_wrapper< T >::value >::template apply< T >::type type;
0056 };
0057 }
0058
0059
0060 template<
0061 class Scheduler,
0062 class WorkItem,
0063 class Allocator = std::allocator< none > >
0064 class processor_container : noncopyable
0065 {
0066 typedef event_processor< Scheduler > processor_base_type;
0067 #ifdef BOOST_NO_AUTO_PTR
0068 typedef std::unique_ptr< processor_base_type > processor_holder_type;
0069 #else
0070 typedef std::auto_ptr< processor_base_type > processor_holder_type;
0071 #endif
0072 typedef shared_ptr< processor_holder_type > processor_holder_ptr_type;
0073
0074 public:
0075
0076 typedef weak_ptr< processor_holder_type > processor_handle;
0077
0078 class processor_context
0079 {
0080 processor_context(
0081 Scheduler & scheduler, const processor_handle & handle
0082 ) :
0083 scheduler_( scheduler ),
0084 handle_( handle )
0085 {
0086 }
0087
0088 #if BOOST_WORKAROUND( BOOST_INTEL, BOOST_TESTED_AT( 800 ) )
0089 public:
0090
0091
0092 #endif
0093
0094 Scheduler & my_scheduler() const { return scheduler_; }
0095 const processor_handle & my_handle() const { return handle_; }
0096
0097 #if BOOST_WORKAROUND( BOOST_INTEL, BOOST_TESTED_AT( 800 ) )
0098 private:
0099 #endif
0100
0101
0102 processor_context & operator=( const processor_context & );
0103
0104 Scheduler & scheduler_;
0105 const processor_handle handle_;
0106
0107 friend class processor_container;
0108 friend class event_processor< Scheduler >;
0109 };
0110
0111 template< class Processor >
0112 WorkItem create_processor( processor_handle & handle, Scheduler & scheduler )
0113 {
0114 processor_holder_ptr_type pProcessor = make_processor_holder();
0115 handle = pProcessor;
0116 typedef void ( processor_container::*impl_fun_ptr )(
0117 const processor_holder_ptr_type &, const processor_context & );
0118 impl_fun_ptr pImpl =
0119 &processor_container::template create_processor_impl0< Processor >;
0120 return WorkItem(
0121 boost::bind( pImpl, this, pProcessor,
0122 processor_context( scheduler, handle ) ),
0123 Allocator() );
0124 }
0125
0126 template< class Processor, typename Arg1 >
0127 WorkItem create_processor(
0128 processor_handle & handle, Scheduler & scheduler, Arg1 arg1 )
0129 {
0130 processor_holder_ptr_type pProcessor = make_processor_holder();
0131 handle = pProcessor;
0132 typedef typename detail::unwrap< Arg1 >::type arg1_type;
0133 typedef void ( processor_container::*impl_fun_ptr )(
0134 const processor_holder_ptr_type &, const processor_context &,
0135 arg1_type );
0136 impl_fun_ptr pImpl =
0137 &processor_container::template create_processor_impl1<
0138 Processor, arg1_type >;
0139 return WorkItem(
0140 boost::bind( pImpl, this, pProcessor, processor_context( scheduler, handle ),
0141 arg1 ),
0142 Allocator() );
0143 }
0144
0145 template< class Processor, typename Arg1, typename Arg2 >
0146 WorkItem create_processor(
0147 processor_handle & handle, Scheduler & scheduler, Arg1 arg1, Arg2 arg2 )
0148 {
0149 processor_holder_ptr_type pProcessor = make_processor_holder();
0150 handle = pProcessor;
0151 typedef typename detail::unwrap< Arg1 >::type arg1_type;
0152 typedef typename detail::unwrap< Arg2 >::type arg2_type;
0153 typedef void ( processor_container::*impl_fun_ptr )(
0154 const processor_holder_ptr_type &, const processor_context &,
0155 arg1_type, arg2_type );
0156 impl_fun_ptr pImpl =
0157 &processor_container::template create_processor_impl2<
0158 Processor, arg1_type, arg2_type >;
0159 return WorkItem(
0160 boost::bind( pImpl, this, pProcessor, processor_context( scheduler, handle ),
0161 arg1, arg2 ),
0162 Allocator() );
0163 }
0164
0165 template< class Processor, typename Arg1, typename Arg2, typename Arg3 >
0166 WorkItem create_processor(
0167 processor_handle & handle, Scheduler & scheduler,
0168 Arg1 arg1, Arg2 arg2, Arg3 arg3 )
0169 {
0170 processor_holder_ptr_type pProcessor = make_processor_holder();
0171 handle = pProcessor;
0172 typedef typename detail::unwrap< Arg1 >::type arg1_type;
0173 typedef typename detail::unwrap< Arg2 >::type arg2_type;
0174 typedef typename detail::unwrap< Arg3 >::type arg3_type;
0175 typedef void ( processor_container::*impl_fun_ptr )(
0176 const processor_holder_ptr_type &, const processor_context &,
0177 arg1_type, arg2_type, arg3_type );
0178 impl_fun_ptr pImpl =
0179 &processor_container::template create_processor_impl3<
0180 Processor, arg1_type, arg2_type, arg3_type >;
0181 return WorkItem(
0182 boost::bind( pImpl, this, pProcessor, processor_context( scheduler, handle ),
0183 arg1, arg2, arg3 ),
0184 Allocator() );
0185 }
0186
0187 template<
0188 class Processor, typename Arg1, typename Arg2,
0189 typename Arg3, typename Arg4 >
0190 WorkItem create_processor(
0191 processor_handle & handle, Scheduler & scheduler,
0192 Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4 )
0193 {
0194 processor_holder_ptr_type pProcessor = make_processor_holder();
0195 handle = pProcessor;
0196 typedef typename detail::unwrap< Arg1 >::type arg1_type;
0197 typedef typename detail::unwrap< Arg2 >::type arg2_type;
0198 typedef typename detail::unwrap< Arg3 >::type arg3_type;
0199 typedef typename detail::unwrap< Arg4 >::type arg4_type;
0200 typedef void ( processor_container::*impl_fun_ptr )(
0201 const processor_holder_ptr_type &, const processor_context &,
0202 arg1_type, arg2_type, arg3_type, arg4_type );
0203 impl_fun_ptr pImpl =
0204 &processor_container::template create_processor_impl4<
0205 Processor, arg1_type, arg2_type, arg3_type, arg4_type >;
0206 return WorkItem(
0207 boost::bind( pImpl, this, pProcessor, processor_context( scheduler, handle ),
0208 arg1, arg2, arg3, arg4 ),
0209 Allocator() );
0210 }
0211
0212 template<
0213 class Processor, typename Arg1, typename Arg2,
0214 typename Arg3, typename Arg4, typename Arg5 >
0215 WorkItem create_processor(
0216 processor_handle & handle, Scheduler & scheduler,
0217 Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5 )
0218 {
0219 processor_holder_ptr_type pProcessor = make_processor_holder();
0220 handle = pProcessor;
0221 typedef typename detail::unwrap< Arg1 >::type arg1_type;
0222 typedef typename detail::unwrap< Arg2 >::type arg2_type;
0223 typedef typename detail::unwrap< Arg3 >::type arg3_type;
0224 typedef typename detail::unwrap< Arg4 >::type arg4_type;
0225 typedef typename detail::unwrap< Arg5 >::type arg5_type;
0226 typedef void ( processor_container::*impl_fun_ptr )(
0227 const processor_holder_ptr_type &, const processor_context &,
0228 arg1_type, arg2_type, arg3_type, arg4_type, arg5_type );
0229 impl_fun_ptr pImpl =
0230 &processor_container::template create_processor_impl5<
0231 Processor, arg1_type, arg2_type, arg3_type, arg4_type, arg5_type >;
0232 return WorkItem(
0233 boost::bind( pImpl, this, pProcessor, processor_context( scheduler, handle ),
0234 arg1, arg2, arg3, arg4, arg5 ),
0235 Allocator() );
0236 }
0237
0238 template<
0239 class Processor, typename Arg1, typename Arg2,
0240 typename Arg3, typename Arg4, typename Arg5, typename Arg6 >
0241 WorkItem create_processor(
0242 processor_handle & handle, Scheduler & scheduler,
0243 Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5, Arg6 arg6 )
0244 {
0245 processor_holder_ptr_type pProcessor = make_processor_holder();
0246 handle = pProcessor;
0247 typedef typename detail::unwrap< Arg1 >::type arg1_type;
0248 typedef typename detail::unwrap< Arg2 >::type arg2_type;
0249 typedef typename detail::unwrap< Arg3 >::type arg3_type;
0250 typedef typename detail::unwrap< Arg4 >::type arg4_type;
0251 typedef typename detail::unwrap< Arg5 >::type arg5_type;
0252 typedef typename detail::unwrap< Arg6 >::type arg6_type;
0253 typedef void ( processor_container::*impl_fun_ptr )(
0254 const processor_holder_ptr_type &, const processor_context &,
0255 arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, arg6_type );
0256 impl_fun_ptr pImpl =
0257 &processor_container::template create_processor_impl6<
0258 Processor,
0259 arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, arg6_type >;
0260 return WorkItem(
0261 boost::bind( pImpl, this, pProcessor, processor_context( scheduler, handle ),
0262 arg1, arg2, arg3, arg4, arg5, arg6 ),
0263 Allocator() );
0264 }
0265
0266 WorkItem destroy_processor( const processor_handle & processor )
0267 {
0268 return WorkItem(
0269 boost::bind( &processor_container::destroy_processor_impl, this, processor ),
0270 Allocator() );
0271 }
0272
0273 WorkItem initiate_processor( const processor_handle & processor )
0274 {
0275 return WorkItem(
0276 boost::bind( &processor_container::initiate_processor_impl, this,
0277 processor ),
0278 Allocator() );
0279 }
0280
0281 WorkItem terminate_processor( const processor_handle & processor )
0282 {
0283 return WorkItem(
0284 boost::bind( &processor_container::terminate_processor_impl, this,
0285 processor ),
0286 Allocator() );
0287 }
0288
0289 typedef intrusive_ptr< const event_base > event_ptr_type;
0290
0291 WorkItem queue_event(
0292 const processor_handle & processor, const event_ptr_type & pEvent )
0293 {
0294 BOOST_ASSERT( pEvent.get() != 0 );
0295
0296 return WorkItem(
0297 boost::bind( &processor_container::queue_event_impl, this, processor,
0298 pEvent ),
0299 Allocator() );
0300 }
0301
0302 private:
0303
0304 processor_holder_ptr_type make_processor_holder()
0305 {
0306 return processor_holder_ptr_type( new processor_holder_type() );
0307 }
0308
0309 template< class Processor >
0310 void create_processor_impl0(
0311 const processor_holder_ptr_type & pProcessor,
0312 const processor_context & context )
0313 {
0314 processorSet_.insert( pProcessor );
0315 *pProcessor = processor_holder_type( new Processor( context ) );
0316 }
0317
0318 template< class Processor, typename Arg1 >
0319 void create_processor_impl1(
0320 const processor_holder_ptr_type & pProcessor,
0321 const processor_context & context, Arg1 arg1 )
0322 {
0323 processorSet_.insert( pProcessor );
0324 *pProcessor = processor_holder_type( new Processor( context, arg1 ) );
0325 }
0326
0327 template< class Processor, typename Arg1, typename Arg2 >
0328 void create_processor_impl2(
0329 const processor_holder_ptr_type & pProcessor,
0330 const processor_context & context, Arg1 arg1, Arg2 arg2 )
0331 {
0332 processorSet_.insert( pProcessor );
0333 *pProcessor = processor_holder_type( new Processor( context, arg1, arg2 ) );
0334 }
0335
0336 template< class Processor, typename Arg1, typename Arg2, typename Arg3 >
0337 void create_processor_impl3(
0338 const processor_holder_ptr_type & pProcessor,
0339 const processor_context & context, Arg1 arg1, Arg2 arg2, Arg3 arg3 )
0340 {
0341 processorSet_.insert( pProcessor );
0342 *pProcessor = processor_holder_type( new Processor( context, arg1, arg2, arg3 ) );
0343 }
0344
0345 template<
0346 class Processor, typename Arg1, typename Arg2,
0347 typename Arg3, typename Arg4 >
0348 void create_processor_impl4(
0349 const processor_holder_ptr_type & pProcessor,
0350 const processor_context & context,
0351 Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4 )
0352 {
0353 processorSet_.insert( pProcessor );
0354 *pProcessor = processor_holder_type( new Processor( context, arg1, arg2, arg3, arg4 ) );
0355 }
0356
0357 template<
0358 class Processor, typename Arg1, typename Arg2,
0359 typename Arg3, typename Arg4, typename Arg5 >
0360 void create_processor_impl5(
0361 const processor_holder_ptr_type & pProcessor,
0362 const processor_context & context,
0363 Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5 )
0364 {
0365 processorSet_.insert( pProcessor );
0366 *pProcessor = processor_holder_type( new Processor( context, arg1, arg2, arg3, arg4, arg5 ) );
0367 }
0368
0369 template<
0370 class Processor, typename Arg1, typename Arg2,
0371 typename Arg3, typename Arg4, typename Arg5, typename Arg6 >
0372 void create_processor_impl6(
0373 const processor_holder_ptr_type & pProcessor,
0374 const processor_context & context,
0375 Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5, Arg6 arg6 )
0376 {
0377 processorSet_.insert( pProcessor );
0378 *pProcessor = processor_holder_type( new Processor( context, arg1, arg2, arg3, arg4, arg5, arg6 ) );
0379 }
0380
0381 void destroy_processor_impl( const processor_handle & processor )
0382 {
0383 const processor_holder_ptr_type pProcessor = processor.lock();
0384
0385 if ( pProcessor != 0 )
0386 {
0387 processorSet_.erase( pProcessor );
0388 }
0389 }
0390
0391 void initiate_processor_impl( const processor_handle & processor )
0392 {
0393 const processor_holder_ptr_type pProcessor = processor.lock();
0394
0395 if ( pProcessor != 0 )
0396 {
0397 ( *pProcessor )->initiate();
0398 }
0399 }
0400
0401 void terminate_processor_impl( const processor_handle & processor )
0402 {
0403 const processor_holder_ptr_type pProcessor = processor.lock();
0404
0405 if ( pProcessor != 0 )
0406 {
0407 ( *pProcessor )->terminate();
0408 }
0409 }
0410
0411 void queue_event_impl(
0412 const processor_handle & processor, const event_ptr_type & pEvent )
0413 {
0414 const processor_holder_ptr_type pProcessor = processor.lock();
0415
0416 if ( pProcessor != 0 )
0417 {
0418 ( *pProcessor )->process_event( *pEvent );
0419 }
0420 }
0421
0422 typedef std::set<
0423 processor_holder_ptr_type,
0424 std::less< processor_holder_ptr_type >,
0425 typename boost::detail::allocator::rebind_to<
0426 Allocator, processor_holder_ptr_type >::type
0427 > event_processor_set_type;
0428
0429 event_processor_set_type processorSet_;
0430 };
0431
0432
0433 }
0434 }
0435
0436
0437
0438 #endif