Advertisement
Guest User

Untitled

a guest
Dec 20th, 2014
257
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.04 KB | None | 0 0
  1.  class MessageDispatcher
  2.     {
  3.     public:
  4.         using Connection        = boost::signals2::connection;
  5.         using ScopedConnection  = boost::signals2::scoped_connection;
  6.  
  7.         MessageDispatcher( const MessageDispatcher& )            = delete;
  8.         MessageDispatcher& operator=( const MessageDispatcher& ) = delete;
  9.  
  10.  
  11.         template< class EventType, class ObserverType >
  12.         Connection on( ObserverType&& observer )
  13.         {
  14.             auto observers = find_or_create_observers<EventType>();
  15.             return observers->connect( std::forward<ObserverType>(observer) );
  16.         }
  17.  
  18.     protected:
  19.  
  20.  
  21.         MessageDispatcher()  = default;
  22.         ~MessageDispatcher() = default;
  23.  
  24.  
  25.         template< class EventType >
  26.         size_t dispatch( const EventType& event )
  27.         {
  28.             if( auto observers = find_observers<EventType>() )
  29.             {
  30.                 return observers->dispatch( event );
  31.             }
  32.             return 0;
  33.         }
  34.  
  35.         template< class EventType >
  36.         unsigned int operator()( const EventType& event ) { return dispatch( std::forward<EventType>(event) ); }
  37.  
  38.  
  39.     private:
  40.  
  41.         class ObserverGroup
  42.         {
  43.         public:
  44.             ObserverGroup( const ObserverGroup& )            = delete;
  45.             ObserverGroup& operator=( const ObserverGroup& ) = delete;
  46.         protected:
  47.             ObserverGroup() = default;
  48.         };
  49.         using ObserverGroupPtr = std::shared_ptr<ObserverGroup>;
  50.  
  51.         using ObserversIndex = tbb::concurrent_unordered_map< type_index, ObserverGroupPtr >;
  52.         ObserversIndex m_observers_index;
  53.  
  54.  
  55.         template< class EventType >
  56.         class EventObservers : public ObserverGroup
  57.         {
  58.             using Signal = boost::signals2::signal< void( EventType )>;
  59.  
  60.             Signal m_signal;
  61.  
  62.         public:
  63.  
  64.             size_t dispatch( const EventType& event )
  65.             {
  66.                 m_signal( event );
  67.                 return m_signal.num_slots();
  68.             }
  69.  
  70.             template< class ObserverType >
  71.             auto connect( ObserverType&& observer )
  72.                 -> typename std::conditional< true, Connection, decltype( observer( std::declval<EventType>() ) ) >::type
  73.             {
  74.                 return m_signal.connect( std::forward<ObserverType>(observer) );
  75.             }
  76.  
  77.             template< class ObserverType >
  78.             auto connect( ObserverType observer )
  79.                 -> typename std::conditional< true, Connection, decltype( observer() ) >::type
  80.             {
  81.                 return m_signal.connect( [=]( const EventType& ){ observer(); } );
  82.             }
  83.  
  84.  
  85.         };
  86.  
  87.         template< class T >
  88.         using ActualType = typename std::decay<T>::type;
  89.  
  90.         template< class EventType >
  91.         using EventObserverPtr = std::shared_ptr< EventObservers< ActualType<EventType> > >;
  92.  
  93.         template< class EventType >
  94.         EventObserverPtr<EventType> find_observers()
  95.         {
  96.             auto find_it = m_observers_index.find( type_id<ActualType<EventType>>() );
  97.             if( find_it != end(m_observers_index) )
  98.                 return std::static_pointer_cast< EventObservers<EventType> >( find_it->second );
  99.             else
  100.                 return nullptr;
  101.         }
  102.  
  103.         template< class EventType >
  104.         EventObserverPtr<EventType> create_observer_group()
  105.         {
  106.             auto new_group = std::make_shared< EventObservers< ActualType<EventType> > >();
  107.             const type_index& type_idx = type_id<ActualType<EventType>>();
  108.             auto insert_info = m_observers_index.insert( std::make_pair( type_idx, new_group ) );
  109.             UCX_ASSERT( insert_info.second == true, "Tried to register a new observer group but there is already an observer group! Type: "
  110.                         << type_idx.pretty_name() );
  111.             return std::static_pointer_cast< EventObservers<EventType> >( insert_info.first->second );
  112.         }
  113.  
  114.         template< class EventType >
  115.         EventObserverPtr<EventType> find_or_create_observers()
  116.         {
  117.             auto observers = find_observers<EventType>();
  118.             if( !observers )
  119.                 observers = create_observer_group<EventType>();
  120.             UCX_ASSERT_NOT_NULL( observers );
  121.             return observers;
  122.         }
  123.  
  124.  
  125.     };
  126.  
  127.     class MessageDispatcher_Immediate
  128.         : public MessageDispatcher
  129.     {
  130.     public:
  131.  
  132.         using MessageDispatcher::dispatch;
  133.         using MessageDispatcher::operator();
  134.  
  135.     };
  136.  
  137.     class MessageDispatcher_Queued
  138.         : public MessageDispatcher
  139.     {
  140.     public:
  141.  
  142.         template< class EventType >
  143.         void publish( EventType event )
  144.         {
  145.             m_event_queue.push( [=]{ MessageDispatcher::dispatch( event ); } );
  146.         }
  147.  
  148.         template< class EventType >
  149.         void operator()( EventType&& event ) { publish( std::forward<EventType>(event) ); }
  150.  
  151.         void dispatch()
  152.         {
  153.             m_event_queue.execute();
  154.         }
  155.  
  156.     private:
  157.  
  158.         WorkQueue<void> m_event_queue;
  159.     };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement