Back to home page

EIC code displayed by LXR

 
 

    


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 // Copyright 2002-2008 Andreas Huber Doenni
0005 // Distributed under the Boost Software License, Version 1.0. (See accompany-
0006 // ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
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       // for some reason Intel 8.0 seems to think that the following functions
0091       // are inaccessible from event_processor<>::event_processor
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         // avoids C4512 (assignment operator could not be generated)
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 } // namespace statechart
0434 } // namespace boost
0435 
0436 
0437 
0438 #endif