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