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