| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438 | #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::unique_ptrnamespace 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< none > >class processor_container : noncopyable{  typedef event_processor< Scheduler > processor_base_type;#ifdef BOOST_NO_AUTO_PTR  typedef std::unique_ptr< processor_base_type > processor_holder_type;#else  typedef std::auto_ptr< processor_base_type > processor_holder_type;#endif  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 );      *pProcessor = processor_holder_type( new Processor( context ) );    }    template< class Processor, typename Arg1 >    void create_processor_impl1(      const processor_holder_ptr_type & pProcessor,      const processor_context & context, Arg1 arg1 )    {      processorSet_.insert( pProcessor );      *pProcessor = processor_holder_type( new Processor( context, arg1 ) );    }    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 );      *pProcessor = processor_holder_type( new Processor( context, arg1, arg2 ) );    }    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 );      *pProcessor = processor_holder_type( new Processor( context, arg1, arg2, arg3 ) );    }    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 );      *pProcessor = processor_holder_type( new Processor( context, arg1, arg2, arg3, arg4 ) );    }    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 );      *pProcessor = processor_holder_type( new Processor( context, arg1, arg2, arg3, arg4, arg5 ) );    }    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 );      *pProcessor = processor_holder_type( new Processor( context, arg1, arg2, arg3, arg4, arg5, arg6 ) );    }    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
 |