1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef mozilla_ThreadEventQueue_h 8 #define mozilla_ThreadEventQueue_h 9 10 #include "mozilla/AbstractEventQueue.h" 11 #include "mozilla/CondVar.h" 12 #include "mozilla/SynchronizedEventQueue.h" 13 #include "nsCOMPtr.h" 14 #include "nsTArray.h" 15 16 class nsIEventTarget; 17 class nsISerialEventTarget; 18 class nsIThreadObserver; 19 20 namespace mozilla { 21 22 class EventQueue; 23 24 template <typename InnerQueueT> 25 class PrioritizedEventQueue; 26 27 class LabeledEventQueue; 28 29 class ThreadEventTarget; 30 31 // A ThreadEventQueue implements normal monitor-style synchronization over the 32 // InnerQueueT AbstractEventQueue. It also implements PushEventQueue and 33 // PopEventQueue for workers (see the documentation below for an explanation of 34 // those). All threads use a ThreadEventQueue as their event queue. InnerQueueT 35 // is a template parameter to avoid virtual dispatch overhead. 36 template <class InnerQueueT> 37 class ThreadEventQueue final : public SynchronizedEventQueue { 38 public: 39 explicit ThreadEventQueue(UniquePtr<InnerQueueT> aQueue); 40 41 bool PutEvent(already_AddRefed<nsIRunnable>&& aEvent, 42 EventPriority aPriority) final; 43 44 already_AddRefed<nsIRunnable> GetEvent(bool aMayWait, 45 EventPriority* aPriority) final; 46 bool HasPendingEvent() final; 47 48 bool ShutdownIfNoPendingEvents() final; 49 Disconnect(const MutexAutoLock & aProofOfLock)50 void Disconnect(const MutexAutoLock& aProofOfLock) final {} 51 52 void EnableInputEventPrioritization() final; 53 void FlushInputEventPrioritization() final; 54 void SuspendInputEventPrioritization() final; 55 void ResumeInputEventPrioritization() final; 56 57 /** 58 * This method causes any events currently enqueued on the thread to be 59 * suppressed until PopEventQueue is called, and any event dispatched to this 60 * thread's nsIEventTarget will queue as well. Calls to PushEventQueue may be 61 * nested and must each be paired with a call to PopEventQueue in order to 62 * restore the original state of the thread. The returned nsIEventTarget may 63 * be used to push events onto the nested queue. Dispatching will be disabled 64 * once the event queue is popped. The thread will only ever process pending 65 * events for the innermost event queue. Must only be called on the target 66 * thread. 67 */ 68 already_AddRefed<nsISerialEventTarget> PushEventQueue(); 69 70 /** 71 * Revert a call to PushEventQueue. When an event queue is popped, any events 72 * remaining in the queue are appended to the elder queue. This also causes 73 * the nsIEventTarget returned from PushEventQueue to stop dispatching events. 74 * Must only be called on the target thread, and with the innermost event 75 * queue. 76 */ 77 void PopEventQueue(nsIEventTarget* aTarget); 78 79 already_AddRefed<nsIThreadObserver> GetObserver() final; 80 already_AddRefed<nsIThreadObserver> GetObserverOnThread() final; 81 void SetObserver(nsIThreadObserver* aObserver) final; 82 MutexRef()83 Mutex& MutexRef() { return mLock; } 84 85 private: 86 class NestedSink; 87 88 virtual ~ThreadEventQueue(); 89 90 bool PutEventInternal(already_AddRefed<nsIRunnable>&& aEvent, 91 EventPriority aPriority, NestedSink* aQueue); 92 93 UniquePtr<InnerQueueT> mBaseQueue; 94 95 struct NestedQueueItem { 96 UniquePtr<EventQueue> mQueue; 97 RefPtr<ThreadEventTarget> mEventTarget; 98 NestedQueueItemNestedQueueItem99 NestedQueueItem(UniquePtr<EventQueue> aQueue, 100 ThreadEventTarget* aEventTarget) 101 : mQueue(Move(aQueue)), mEventTarget(aEventTarget) {} 102 }; 103 104 nsTArray<NestedQueueItem> mNestedQueues; 105 106 Mutex mLock; 107 CondVar mEventsAvailable; 108 109 bool mEventsAreDoomed = false; 110 nsCOMPtr<nsIThreadObserver> mObserver; 111 }; 112 113 extern template class ThreadEventQueue<EventQueue>; 114 extern template class ThreadEventQueue<PrioritizedEventQueue<EventQueue>>; 115 extern template class ThreadEventQueue< 116 PrioritizedEventQueue<LabeledEventQueue>>; 117 118 }; // namespace mozilla 119 120 #endif // mozilla_ThreadEventQueue_h 121