Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- class MessageDispatcher
- {
- public:
- using Connection = boost::signals2::connection;
- using ScopedConnection = boost::signals2::scoped_connection;
- MessageDispatcher( const MessageDispatcher& ) = delete;
- MessageDispatcher& operator=( const MessageDispatcher& ) = delete;
- template< class EventType, class ObserverType >
- Connection on( ObserverType&& observer )
- {
- auto observers = find_or_create_observers<EventType>();
- return observers->connect( std::forward<ObserverType>(observer) );
- }
- protected:
- MessageDispatcher() = default;
- ~MessageDispatcher() = default;
- template< class EventType >
- size_t dispatch( const EventType& event )
- {
- if( auto observers = find_observers<EventType>() )
- {
- return observers->dispatch( event );
- }
- return 0;
- }
- template< class EventType >
- unsigned int operator()( const EventType& event ) { return dispatch( std::forward<EventType>(event) ); }
- private:
- class ObserverGroup
- {
- public:
- ObserverGroup( const ObserverGroup& ) = delete;
- ObserverGroup& operator=( const ObserverGroup& ) = delete;
- protected:
- ObserverGroup() = default;
- };
- using ObserverGroupPtr = std::shared_ptr<ObserverGroup>;
- using ObserversIndex = tbb::concurrent_unordered_map< type_index, ObserverGroupPtr >;
- ObserversIndex m_observers_index;
- template< class EventType >
- class EventObservers : public ObserverGroup
- {
- using Signal = boost::signals2::signal< void( EventType )>;
- Signal m_signal;
- public:
- size_t dispatch( const EventType& event )
- {
- m_signal( event );
- return m_signal.num_slots();
- }
- template< class ObserverType >
- auto connect( ObserverType&& observer )
- -> typename std::conditional< true, Connection, decltype( observer( std::declval<EventType>() ) ) >::type
- {
- return m_signal.connect( std::forward<ObserverType>(observer) );
- }
- template< class ObserverType >
- auto connect( ObserverType observer )
- -> typename std::conditional< true, Connection, decltype( observer() ) >::type
- {
- return m_signal.connect( [=]( const EventType& ){ observer(); } );
- }
- };
- template< class T >
- using ActualType = typename std::decay<T>::type;
- template< class EventType >
- using EventObserverPtr = std::shared_ptr< EventObservers< ActualType<EventType> > >;
- template< class EventType >
- EventObserverPtr<EventType> find_observers()
- {
- auto find_it = m_observers_index.find( type_id<ActualType<EventType>>() );
- if( find_it != end(m_observers_index) )
- return std::static_pointer_cast< EventObservers<EventType> >( find_it->second );
- else
- return nullptr;
- }
- template< class EventType >
- EventObserverPtr<EventType> create_observer_group()
- {
- auto new_group = std::make_shared< EventObservers< ActualType<EventType> > >();
- const type_index& type_idx = type_id<ActualType<EventType>>();
- auto insert_info = m_observers_index.insert( std::make_pair( type_idx, new_group ) );
- UCX_ASSERT( insert_info.second == true, "Tried to register a new observer group but there is already an observer group! Type: "
- << type_idx.pretty_name() );
- return std::static_pointer_cast< EventObservers<EventType> >( insert_info.first->second );
- }
- template< class EventType >
- EventObserverPtr<EventType> find_or_create_observers()
- {
- auto observers = find_observers<EventType>();
- if( !observers )
- observers = create_observer_group<EventType>();
- UCX_ASSERT_NOT_NULL( observers );
- return observers;
- }
- };
- class MessageDispatcher_Immediate
- : public MessageDispatcher
- {
- public:
- using MessageDispatcher::dispatch;
- using MessageDispatcher::operator();
- };
- class MessageDispatcher_Queued
- : public MessageDispatcher
- {
- public:
- template< class EventType >
- void publish( EventType event )
- {
- m_event_queue.push( [=]{ MessageDispatcher::dispatch( event ); } );
- }
- template< class EventType >
- void operator()( EventType&& event ) { publish( std::forward<EventType>(event) ); }
- void dispatch()
- {
- m_event_queue.execute();
- }
- private:
- WorkQueue<void> m_event_queue;
- };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement