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