You.i Engine
YiEventDispatcher.h
Go to the documentation of this file.
1 // © You i Labs Inc. 2000-2020. All rights reserved.
2 #ifndef _YI_EVENT_DISPATCHER_H_
3 #define _YI_EVENT_DISPATCHER_H_
4 
6 #include "event/YiEvent.h"
7 #include "framework/YiPredef.h"
8 #include "logging/YiLogger.h"
11 #include "thread/YiThread.h"
12 
13 #include <condition_variable>
14 #include <memory>
15 #include <mutex>
16 
17 class CYIEventDispatcher;
18 class CYIEventHandler;
20 class CYIEventFilter;
22 class CYISignalEmitEventHandler;
25 
26 enum class EYIPriorityQueuePriority;
27 template<typename YI_PRIORITY_QUEUE_ITEM, class YI_PRIORITY_QUEUE_ALLOCATOR>
29 
39 {
40 public:
43 
44  virtual void EventLoopStarted(const std::shared_ptr<CYIEventDispatcher> &pDispatcher) = 0;
45 
46  virtual void EventLoopExited(const std::shared_ptr<CYIEventDispatcher> &pDispatcher) = 0;
47 
48  virtual void EventDispatchStarted(const std::shared_ptr<CYIEventDispatcher> &pDispatcher, CYIEvent *pEvent) = 0;
49 
50  virtual void EventDispatchEnded(const std::shared_ptr<CYIEventDispatcher> &pDispatcher, CYIEvent *pEvent) = 0;
51 
52  virtual void EventPreFilteredByDispatcher(const std::shared_ptr<CYIEventDispatcher> &pDispatcher, CYIEvent *pEvent, CYIEventFilter *pFilter) = 0;
53 
54  virtual void EventPreFilteredByHandler(const std::shared_ptr<CYIEventDispatcher> &pDispatcher, CYIEvent *pEvent, CYIEventFilter *pFilter, CYIEventHandler *pHandler) = 0;
55 
56  virtual void EventHandled(const std::shared_ptr<CYIEventDispatcher> &pDispatcher, CYIEvent *pEvent, CYIEventHandler *pHandler) = 0;
57 
58  virtual void EventPostFilteredByHandler(const std::shared_ptr<CYIEventDispatcher> &pDispatcher, CYIEvent *pEvent, CYIEventFilter *pFilter, CYIEventHandler *pHandler) = 0;
59 
60  virtual void EventPostFilteredByDispatcher(const std::shared_ptr<CYIEventDispatcher> &pDispatcher, CYIEvent *pEvent, CYIEventFilter *pFilter) = 0;
61 };
62 
66 class CYIEventDispatcher : public CYISignalHandler, public std::enable_shared_from_this<CYIEventDispatcher>
67 {
68  friend class CYIEventHandler;
69 
70  typedef std::deque<std::shared_ptr<CYIEventHandlerProxy>> YI_EVENT_HANDLER_LIST;
71  typedef std::deque<std::shared_ptr<CYIEventFilterProxy>> YI_EVENT_FILTER_LIST;
72  typedef std::deque<IYIEventDispatcherListener *> YI_EVENT_DISPATCHER_LISTENER_LIST;
73  typedef CYIPriorityQueue<std::pair<std::unique_ptr<CYIEvent>, std::shared_ptr<CYIEventHandlerProxy>>, std::allocator<std::pair<EYIPriorityQueuePriority, std::pair<std::unique_ptr<CYIEvent>, std::shared_ptr<CYIEventHandlerProxy>>>>> YI_EVENT_QUEUE;
74  typedef std::vector<std::pair<CYIThreadHandle, std::shared_ptr<CYIEventDispatcher>>> YI_DISPATCHER_MAP;
75 
76 public:
84  enum class Priority
85  {
86  High,
87  Low
88  };
89 
91  virtual ~CYIEventDispatcher();
92 
96  bool Start();
97 
105  bool Exit(bool join = false, bool waitUntilEmpty = false);
106 
110  void WaitUntilEventQueueRunning();
111 
120  bool WaitUntilEventPosted(uint64_t timeoutMs = 0);
121 
127  bool ProcessOneEvent();
128 
134  bool ProcessAllEvents();
135 
139  bool ProcessAllEvents(uint64_t timeoutUs);
140 
150  bool ProcessEventsOfType(CYIEvent::Type type);
151 
163  bool ProcessEventsOfTypes(const std::vector<CYIEvent::Type> &types);
164 
181  bool RegisterEventHandler(CYIEventHandler *pEventHandler, Priority priority = Priority::Low);
182 
198  bool UnregisterEventHandler(CYIEventHandler *pEventHandler);
199 
214  bool RegisterEventFilter(CYIEventFilter *pEventFilter, Priority priority = Priority::Low);
215 
227  bool UnregisterEventFilter(CYIEventFilter *pEventFilter);
228 
234  bool RegisterEventDispatcherListener(IYIEventDispatcherListener *pEventDispatcherListener, Priority priority = Priority::Low);
235 
241  bool UnregisterEventDispatcherListener(IYIEventDispatcherListener *pEventDispatcherListener);
242 
248  bool PostEvent(std::unique_ptr<CYIEvent> pEvent, CYIEvent::Priority priority = CYIEvent::Priority::Default, bool bump = false);
249 
253  bool PostEvent(std::unique_ptr<CYIEvent> pEvent, CYIEventHandler *pDestination, CYIEvent::Priority priority = CYIEvent::Priority::Default, bool bump = false);
254 
258  bool PostUniqueEvent(std::unique_ptr<CYIEvent> pEvent, CYIEvent::Priority priority = CYIEvent::Priority::Default);
259 
265  bool PostUniqueEvent(std::unique_ptr<CYIEvent> pEvent, CYIEventHandler *pDestination, CYIEvent::Priority priority = CYIEvent::Priority::Default);
266 
286  bool SendEvent(std::unique_ptr<CYIEvent> pEvent);
287 
309  bool SendEvent(std::unique_ptr<CYIEvent> pEvent, CYIEventHandler *pDestination);
310 
314  size_t GetEventCount() const;
315 
321  void Shutdown();
322 
326  void DiscardAllPosts();
327 
331  void DiscardPosts(CYIEventHandler *pDestination);
332 
336  void DiscardPostsIf(bool (*predicate)(const std::shared_ptr<CYIEventDispatcher> &, CYIEvent *, CYIEventHandler *, CYIEvent::Priority));
337 
341  static std::shared_ptr<CYIEventDispatcher> GetDispatcher(const CYIThreadHandle &threadAffinity);
342 
346  static const std::shared_ptr<CYIEventDispatcher> &GetDefaultDispatcher();
347 
351  static const CYIThreadHandle &GetDefaultDispatcherThreadAffinity();
352 
358  static const std::shared_ptr<CYIEventDispatcher> &GetDrawDispatcher();
359 
363  static void SetDispatcher(const CYIThreadHandle &threadAffinity, const std::shared_ptr<CYIEventDispatcher> &pDispatcher);
364 
368  static void RemoveDispatcher(const CYIThreadHandle &threadAffinity);
369 
373  static void SetDefaultDispatcher(const std::shared_ptr<CYIEventDispatcher> &pDispatcher);
374 
378  static void RemoveDefaultDispatcher();
379 
383  static void SetDrawDispatcher(const std::shared_ptr<CYIEventDispatcher> &pDispatcher);
384 
388  static void RemoveDrawDispatcher();
389 
393  CYIEventHandler *GetSignalEmitEventHandler();
394 
398  CYIEventHandler *GetDeferredDeletionEventHandler();
399 
403  CYIEventHandler *GetTaskEventHandler();
404 
405 private:
407  CYIEventDispatcher &operator=(const CYIEventDispatcher &);
408 
409  bool PreFilter(CYIEvent *pEvent, const std::shared_ptr<CYIEventHandlerProxy> &pDestination);
410  bool PostFilter(CYIEvent *pEvent, const std::shared_ptr<CYIEventHandlerProxy> &pDestination);
411  bool DispatchEvent(CYIEvent *pEvent, const std::shared_ptr<CYIEventHandlerProxy> &pDestination);
412  bool ProcessEvent(CYIEvent *pEvent, const std::shared_ptr<CYIEventHandlerProxy> &pDestination);
413 
414  bool ProcessEventsOfTypes(const CYIEvent::Type *pFirstItem, size_t count);
415 
416  void NotifyEventLoopStarted();
417  void NotifyEventLoopExited();
418  void NotifyEventDispatchStarted(CYIEvent *pEvent);
419  void NotifyEventDispatchEnded(CYIEvent *pEvent);
420  void NotifyEventPreFilteredByDispatcher(CYIEvent *pEvent, CYIEventFilter *pFilter);
421  void NotifyEventPreFilteredByHandler(CYIEvent *pEvent, CYIEventFilter *pFilter, CYIEventHandler *pHandler);
422  void NotifyEventHandled(CYIEvent *pEvent, CYIEventHandler *pHandler);
423  void NotifyEventPostFilteredByHandler(CYIEvent *pEvent, CYIEventFilter *pFilter, CYIEventHandler *pHandler);
424  void NotifyEventPostFilteredByDispatcher(CYIEvent *pEvent, CYIEventFilter *pFilter);
425 
426  bool m_eventQueueRunning;
427 
428  std::unique_ptr<CYISignalEmitEventHandler> m_pSignalEmitEventHandler;
429  std::unique_ptr<CYIDeferredDeletionEventHandler> m_pDeferredDeletionEventHandler;
430  std::unique_ptr<CYITaskEventHandler> m_pTaskEventHandler;
431 
432  YI_EVENT_HANDLER_LIST m_eventHandlerList;
433  YI_EVENT_FILTER_LIST m_eventFilterList;
434  YI_EVENT_DISPATCHER_LISTENER_LIST m_eventDispatcherListenerList;
435  std::unique_ptr<YI_EVENT_QUEUE> m_pEventQueue;
436 
437  CYILazy<std::mutex> m_eventHandlerListMutex;
438  CYILazy<std::mutex> m_eventFilterListMutex;
439  CYILazy<std::mutex> m_eventDispatcherListenerListMutex;
440 
441  mutable std::mutex m_eventQueueMutex;
442  std::condition_variable m_eventQueueWaitCondition;
443  std::condition_variable m_waitUntilEventWaitCondition;
444 
445  static YI_DISPATCHER_MAP s_dispatcherMap;
446  static std::shared_ptr<CYIEventDispatcher> s_dispatcherDefault;
447  static CYIThreadHandle s_dispatcherDefaultThreadAffinity;
448  static std::shared_ptr<CYIEventDispatcher> s_dispatcherDraw;
449  static CYIReadWriteMutex s_dispatcherMapMutex;
450 };
451 
457 template<typename YI_TYPE>
458 inline void YiDeleteLater(std::unique_ptr<YI_TYPE> pPtr)
459 {
460  if (pPtr)
461  {
462  std::shared_ptr<CYIEventDispatcher> pDispatcher = CYIEventDispatcher::GetDispatcher(CYIThread::GetCurrentThreadId());
463  if (!pDispatcher)
464  {
466  }
467 
468  if (!pDispatcher)
469  {
470  YI_LOGD("YiDeleteLater", "No event dispatcher. YiDeleteLater called while the application is shutting down, so deleting ptr immediately.");
471  // If we can't delete later, we have to delete now to avoid a memory leak. This will occur during shutdown when the CYIDeferredDeletionEvent is deleting the pPtr, and it in turn results in a YiDeleteLater being called.
472  pPtr.reset();
473  return;
474  }
475 
476  pDispatcher->PostEvent(std::unique_ptr<CYIEvent>(new CYIDeferredDeletionEvent<YI_TYPE>(std::move(pPtr))), pDispatcher->GetDeferredDeletionEventHandler(), CYIEvent::Priority::Highest);
477  }
478 }
479 
482 #endif /* _YI_EVENT_DISPATCHER_H_ */
virtual void EventPostFilteredByHandler(const std::shared_ptr< CYIEventDispatcher > &pDispatcher, CYIEvent *pEvent, CYIEventFilter *pFilter, CYIEventHandler *pHandler)=0
Allows registering of event filters which can be used to perform processing on an event before and af...
Definition: YiEventHandler.h:25
#define YI_LOGD(tag, message,...)
Definition: YiLogger.h:129
Base class for events.
Definition: YiEvent.h:27
static std::shared_ptr< CYIEventDispatcher > GetDispatcher(const CYIThreadHandle &threadAffinity)
virtual ~IYIEventDispatcherListener()
Definition: YiEventDispatcher.h:42
virtual void EventDispatchStarted(const std::shared_ptr< CYIEventDispatcher > &pDispatcher, CYIEvent *pEvent)=0
virtual void EventDispatchEnded(const std::shared_ptr< CYIEventDispatcher > &pDispatcher, CYIEvent *pEvent)=0
Proxy for a CYIEventFilter allowing safe destruction of the internal event filter objects...
Definition: YiEventFilterProxy.h:24
static const std::shared_ptr< CYIEventDispatcher > & GetDefaultDispatcher()
Definition: YiEventDispatcher.h:28
virtual void EventHandled(const std::shared_ptr< CYIEventDispatcher > &pDispatcher, CYIEvent *pEvent, CYIEventHandler *pHandler)=0
Handles events where data deletion needs to be deferred.
Definition: YiDeferredDeletionEventHandler.h:17
static CYIThreadHandle GetCurrentThreadId()
Definition: YiReadWriteMutex.h:16
Definition: YiSignalHandler.h:175
virtual void EventLoopExited(const std::shared_ptr< CYIEventDispatcher > &pDispatcher)=0
virtual void EventLoopStarted(const std::shared_ptr< CYIEventDispatcher > &pDispatcher)=0
virtual void EventPreFilteredByDispatcher(const std::shared_ptr< CYIEventDispatcher > &pDispatcher, CYIEvent *pEvent, CYIEventFilter *pFilter)=0
Priority
Definition: YiEventDispatcher.h:84
Handles events where tasks are executed when the event is processed on an event queue.
Definition: YiTaskEventHandler.h:15
Stores, queues and dispatches events as well as sending notifications to IYIEventDispatcherListener o...
Definition: YiEventDispatcher.h:66
Allows children that inherit from this class to implement processing before and after events are hand...
Definition: YiEventFilter.h:24
void YiDeleteLater(std::unique_ptr< YI_TYPE > pPtr)
Adds the given pointer to the deferred deletion queue.
Definition: YiEventDispatcher.h:458
IYIEventDispatcherListener()
Definition: YiEventDispatcher.h:41
Implementors of this Listener interface can register themselves with the CYIEventDispather and become...
Definition: YiEventDispatcher.h:38
Priority
Priority of the event in the event queue.
Definition: YiEvent.h:99
Definition: YiThreadHandle.h:45
virtual void EventPreFilteredByHandler(const std::shared_ptr< CYIEventDispatcher > &pDispatcher, CYIEvent *pEvent, CYIEventFilter *pFilter, CYIEventHandler *pHandler)=0
Proxy for a CYIEventHandler allowing safe destruction of the internal event handler objects...
Definition: YiEventHandlerProxy.h:25
virtual void EventPostFilteredByDispatcher(const std::shared_ptr< CYIEventDispatcher > &pDispatcher, CYIEvent *pEvent, CYIEventFilter *pFilter)=0
Event for handling deferred deletion of data of type YI_TYPE. SfinaeHelper type is used to control a ...
Definition: YiDeferredDeletionEvent.h:30
Type
The event type of the CYIEvent class instance.
Definition: YiEvent.h:33