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_EventQueue_h 8 #define mozilla_EventQueue_h 9 10 #include "mozilla/Mutex.h" 11 #include "mozilla/Queue.h" 12 #include "mozilla/TimeStamp.h" 13 #include "nsCOMPtr.h" 14 15 class nsIRunnable; 16 17 namespace mozilla { 18 19 enum class EventQueuePriority { 20 Idle, 21 DeferredTimers, 22 InputLow, 23 Normal, 24 MediumHigh, 25 InputHigh, 26 Vsync, 27 InputHighest, 28 RenderBlocking, 29 Control, 30 31 Count 32 }; 33 34 class IdlePeriodState; 35 36 namespace detail { 37 38 // EventQueue is our unsynchronized event queue implementation. It is a queue 39 // of runnables used for non-main thread, as well as optionally providing 40 // forwarding to TaskController. 41 // 42 // Since EventQueue is unsynchronized, it should be wrapped in an outer 43 // SynchronizedEventQueue implementation (like ThreadEventQueue). 44 template <size_t ItemsPerPage> 45 class EventQueueInternal { 46 public: EventQueueInternal(bool aForwardToTC)47 explicit EventQueueInternal(bool aForwardToTC) : mForwardToTC(aForwardToTC) {} 48 49 // Add an event to the end of the queue. Implementors are free to use 50 // aPriority however they wish. If the runnable supports 51 // nsIRunnablePriority and the implementing class supports 52 // prioritization, aPriority represents the result of calling 53 // nsIRunnablePriority::GetPriority(). *aDelay is time the event has 54 // already been delayed (used when moving an event from one queue to 55 // another) 56 void PutEvent(already_AddRefed<nsIRunnable>&& aEvent, 57 EventQueuePriority aPriority, const MutexAutoLock& aProofOfLock, 58 mozilla::TimeDuration* aDelay = nullptr); 59 60 // Get an event from the front of the queue. This should return null if the 61 // queue is non-empty but the event in front is not ready to run. 62 // *aLastEventDelay is the time the event spent in queues before being 63 // retrieved. 64 already_AddRefed<nsIRunnable> GetEvent( 65 const MutexAutoLock& aProofOfLock, 66 mozilla::TimeDuration* aLastEventDelay = nullptr); 67 68 // Returns true if the queue is empty. Implies !HasReadyEvent(). 69 bool IsEmpty(const MutexAutoLock& aProofOfLock); 70 71 // Returns true if the queue is non-empty and if the event in front is ready 72 // to run. Implies !IsEmpty(). This should return true iff GetEvent returns a 73 // non-null value. 74 bool HasReadyEvent(const MutexAutoLock& aProofOfLock); 75 76 // Returns the number of events in the queue. 77 size_t Count(const MutexAutoLock& aProofOfLock) const; 78 // For some reason, if we put this in the .cpp file the linker can't find it PeekEvent(const MutexAutoLock & aProofOfLock)79 already_AddRefed<nsIRunnable> PeekEvent(const MutexAutoLock& aProofOfLock) { 80 if (mQueue.IsEmpty()) { 81 return nullptr; 82 } 83 84 nsCOMPtr<nsIRunnable> result = mQueue.FirstElement(); 85 return result.forget(); 86 } 87 EnableInputEventPrioritization(const MutexAutoLock & aProofOfLock)88 void EnableInputEventPrioritization(const MutexAutoLock& aProofOfLock) {} FlushInputEventPrioritization(const MutexAutoLock & aProofOfLock)89 void FlushInputEventPrioritization(const MutexAutoLock& aProofOfLock) {} SuspendInputEventPrioritization(const MutexAutoLock & aProofOfLock)90 void SuspendInputEventPrioritization(const MutexAutoLock& aProofOfLock) {} ResumeInputEventPrioritization(const MutexAutoLock & aProofOfLock)91 void ResumeInputEventPrioritization(const MutexAutoLock& aProofOfLock) {} 92 SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)93 size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const { 94 return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf); 95 } 96 SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf)97 size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const { 98 size_t size = mQueue.ShallowSizeOfExcludingThis(aMallocSizeOf); 99 size += mDispatchTimes.ShallowSizeOfExcludingThis(aMallocSizeOf); 100 return size; 101 } 102 103 private: 104 mozilla::Queue<nsCOMPtr<nsIRunnable>, ItemsPerPage> mQueue; 105 // This queue is only populated when the profiler is turned on. 106 mozilla::Queue<mozilla::TimeStamp, ItemsPerPage> mDispatchTimes; 107 TimeDuration mLastEventDelay; 108 // This indicates PutEvent forwards runnables to the TaskController. This 109 // should be true for the top level event queue on the main thread. 110 bool mForwardToTC; 111 }; 112 113 } // namespace detail 114 115 class EventQueue final : public mozilla::detail::EventQueueInternal<16> { 116 public: 117 explicit EventQueue(bool aForwardToTC = false) 118 : mozilla::detail::EventQueueInternal<16>(aForwardToTC) {} 119 }; 120 121 template <size_t ItemsPerPage = 16> 122 class EventQueueSized final 123 : public mozilla::detail::EventQueueInternal<ItemsPerPage> { 124 public: 125 explicit EventQueueSized(bool aForwardToTC = false) 126 : mozilla::detail::EventQueueInternal<ItemsPerPage>(aForwardToTC) {} 127 }; 128 129 } // namespace mozilla 130 131 #endif // mozilla_EventQueue_h 132