Bug 1597728: Make EventQueue support templatization for queue page size r=froydnj

Most event queues don't ever get many events queued at one time, but the
MainThread Input and Normal queues may.

Differential Revision: https://phabricator.services.mozilla.com/D53912

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Randell Jesup 2019-11-21 03:47:19 +00:00
Родитель ede385148e
Коммит 6835880244
6 изменённых файлов: 80 добавлений и 36 удалений

Просмотреть файл

@ -8,13 +8,16 @@
#include "nsIRunnable.h"
using namespace mozilla;
using namespace mozilla::detail;
EventQueue::EventQueue(EventQueuePriority aPriority) {}
template <size_t ItemsPerPage>
EventQueueInternal<ItemsPerPage>::EventQueueInternal(
EventQueuePriority aPriority) {}
void EventQueue::PutEvent(already_AddRefed<nsIRunnable>&& aEvent,
EventQueuePriority aPriority,
const MutexAutoLock& aProofOfLock,
mozilla::TimeDuration* aDelay) {
template <size_t ItemsPerPage>
void EventQueueInternal<ItemsPerPage>::PutEvent(
already_AddRefed<nsIRunnable>&& aEvent, EventQueuePriority aPriority,
const MutexAutoLock& aProofOfLock, mozilla::TimeDuration* aDelay) {
#ifdef MOZ_GECKO_PROFILER
// Sigh, this doesn't check if this thread is being profiled
if (profiler_is_active()) {
@ -30,7 +33,8 @@ void EventQueue::PutEvent(already_AddRefed<nsIRunnable>&& aEvent,
mQueue.Push(std::move(event));
}
already_AddRefed<nsIRunnable> EventQueue::GetEvent(
template <size_t ItemsPerPage>
already_AddRefed<nsIRunnable> EventQueueInternal<ItemsPerPage>::GetEvent(
EventQueuePriority* aPriority, const MutexAutoLock& aProofOfLock,
mozilla::TimeDuration* aLastEventDelay) {
if (mQueue.IsEmpty()) {
@ -71,24 +75,20 @@ already_AddRefed<nsIRunnable> EventQueue::GetEvent(
return result.forget();
}
bool EventQueue::IsEmpty(const MutexAutoLock& aProofOfLock) {
template <size_t ItemsPerPage>
bool EventQueueInternal<ItemsPerPage>::IsEmpty(
const MutexAutoLock& aProofOfLock) {
return mQueue.IsEmpty();
}
bool EventQueue::HasReadyEvent(const MutexAutoLock& aProofOfLock) {
template <size_t ItemsPerPage>
bool EventQueueInternal<ItemsPerPage>::HasReadyEvent(
const MutexAutoLock& aProofOfLock) {
return !IsEmpty(aProofOfLock);
}
already_AddRefed<nsIRunnable> EventQueue::PeekEvent(
const MutexAutoLock& aProofOfLock) {
if (mQueue.IsEmpty()) {
return nullptr;
}
nsCOMPtr<nsIRunnable> result = mQueue.FirstElement();
return result.forget();
}
size_t EventQueue::Count(const MutexAutoLock& aProofOfLock) const {
template <size_t ItemsPerPage>
size_t EventQueueInternal<ItemsPerPage>::Count(
const MutexAutoLock& aProofOfLock) const {
return mQueue.Count();
}

Просмотреть файл

@ -15,12 +15,15 @@ class nsIRunnable;
namespace mozilla {
class EventQueue final : public AbstractEventQueue {
namespace detail {
template <size_t ItemsPerPage>
class EventQueueInternal : public AbstractEventQueue {
public:
static const bool SupportsPrioritization = false;
EventQueue() {}
explicit EventQueue(EventQueuePriority aPriority);
EventQueueInternal() {}
explicit EventQueueInternal(EventQueuePriority aPriority);
void PutEvent(already_AddRefed<nsIRunnable>&& aEvent,
EventQueuePriority aPriority, const MutexAutoLock& aProofOfLock,
@ -33,12 +36,20 @@ class EventQueue final : public AbstractEventQueue {
bool IsEmpty(const MutexAutoLock& aProofOfLock) final;
bool HasReadyEvent(const MutexAutoLock& aProofOfLock) final;
bool HasPendingHighPriorityEvents(const MutexAutoLock& aProofOfLock) final {
// EventQueue doesn't support any prioritization.
// EventQueueInternal doesn't support any prioritization.
return false;
}
size_t Count(const MutexAutoLock& aProofOfLock) const final;
already_AddRefed<nsIRunnable> PeekEvent(const MutexAutoLock& aProofOfLock);
// 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) final {
}
@ -58,14 +69,32 @@ class EventQueue final : public AbstractEventQueue {
}
private:
mozilla::Queue<nsCOMPtr<nsIRunnable>, 16> mQueue;
mozilla::Queue<nsCOMPtr<nsIRunnable>, ItemsPerPage> mQueue;
#ifdef MOZ_GECKO_PROFILER
// This queue is only populated when the profiler is turned on.
mozilla::Queue<mozilla::TimeStamp, 16> mDispatchTimes;
mozilla::Queue<mozilla::TimeStamp, ItemsPerPage> mDispatchTimes;
TimeDuration mLastEventDelay;
#endif
};
} // namespace detail
class EventQueue final : public mozilla::detail::EventQueueInternal<16> {
public:
EventQueue() : mozilla::detail::EventQueueInternal<16>() {}
explicit EventQueue(EventQueuePriority aPriority)
: mozilla::detail::EventQueueInternal<16>(aPriority){};
};
template <size_t ItemsPerPage = 16>
class EventQueueSized final
: public mozilla::detail::EventQueueInternal<ItemsPerPage> {
public:
EventQueueSized() : mozilla::detail::EventQueueInternal<ItemsPerPage>() {}
explicit EventQueueSized(EventQueuePriority aPriority)
: mozilla::detail::EventQueueInternal<ItemsPerPage>(aPriority){};
};
} // namespace mozilla
#endif // mozilla_EventQueue_h

Просмотреть файл

@ -18,9 +18,9 @@ using namespace mozilla;
PrioritizedEventQueue::PrioritizedEventQueue(
already_AddRefed<nsIIdlePeriod>&& aIdlePeriod)
: mHighQueue(MakeUnique<EventQueue>(EventQueuePriority::High)),
mInputQueue(MakeUnique<EventQueue>(EventQueuePriority::Input)),
mInputQueue(MakeUnique<EventQueueSized<32>>(EventQueuePriority::Input)),
mMediumHighQueue(MakeUnique<EventQueue>(EventQueuePriority::MediumHigh)),
mNormalQueue(MakeUnique<EventQueue>(EventQueuePriority::Normal)),
mNormalQueue(MakeUnique<EventQueueSized<64>>(EventQueuePriority::Normal)),
mDeferredTimersQueue(
MakeUnique<EventQueue>(EventQueuePriority::DeferredTimers)),
mIdleQueue(MakeUnique<EventQueue>(EventQueuePriority::Idle)),

Просмотреть файл

@ -95,9 +95,9 @@ class PrioritizedEventQueue final : public AbstractEventQueue {
const MutexAutoLock& aProofOfLock);
UniquePtr<EventQueue> mHighQueue;
UniquePtr<EventQueue> mInputQueue;
UniquePtr<EventQueueSized<32>> mInputQueue;
UniquePtr<EventQueue> mMediumHighQueue;
UniquePtr<EventQueue> mNormalQueue;
UniquePtr<EventQueueSized<64>> mNormalQueue;
UniquePtr<EventQueue> mDeferredTimersQueue;
UniquePtr<EventQueue> mIdleQueue;

Просмотреть файл

@ -11,6 +11,9 @@
namespace mozilla {
// define to turn on additional (DEBUG) asserts
// #define EXTRA_ASSERTS 1
// A queue implements a singly linked list of pages, each of which contains some
// number of elements. Since the queue needs to store a "next" pointer, the
// actual number of elements per page won't be quite as many as were requested.
@ -59,6 +62,9 @@ class Queue {
}
T& Push(T&& aElement) {
#if defined(EXTRA_ASSERTS) && DEBUG
size_t original_length = Count();
#endif
if (!mHead) {
mHead = NewPage();
MOZ_ASSERT(mHead);
@ -103,6 +109,9 @@ class Queue {
// else we have space to insert into last buffer
T& eltLocation = mTail->mEvents[mTailLength++];
eltLocation = std::move(aElement);
#ifdef EXTRA_ASSERTS
MOZ_ASSERT(Count() == original_length + 1);
#endif
return eltLocation;
}
@ -111,6 +120,9 @@ class Queue {
}
T Pop() {
#if defined(EXTRA_ASSERTS) && DEBUG
size_t original_length = Count();
#endif
MOZ_ASSERT(!IsEmpty());
T result = std::move(mHead->mEvents[mOffsetHead]);
@ -133,28 +145,31 @@ class Queue {
}
}
#ifdef EXTRA_ASSERTS
MOZ_ASSERT(Count() == original_length - 1);
#endif
return result;
}
T& FirstElement() {
FirstElementAssertions();
MOZ_ASSERT(!IsEmpty());
return mHead->mEvents[mOffsetHead];
}
const T& FirstElement() const {
FirstElementAssertions();
MOZ_ASSERT(!IsEmpty());
return mHead->mEvents[mOffsetHead];
}
T& LastElement() {
LastElementAssertions();
MOZ_ASSERT(!IsEmpty());
uint16_t offset =
mHead == mTail ? mOffsetHead + mHeadLength - 1 : mTailLength - 1;
return mTail->mEvents[offset];
}
const T& LastElement() const {
LastElementAssertions();
MOZ_ASSERT(!IsEmpty());
uint16_t offset =
mHead == mTail ? mOffsetHead + mHeadLength - 1 : mTailLength - 1;
return mTail->mEvents[offset];
@ -173,7 +188,7 @@ class Queue {
page = page->mNext) {
count += ItemsPerPage;
}
// add first and last page
count += mHeadLength + mTailLength;
MOZ_ASSERT(count >= 0);

Просмотреть файл

@ -100,7 +100,7 @@ class ThrottledEventQueue::Inner final : public nsISupports {
//
// Used from any thread; protected by mMutex. Signals mIdleCondVar when
// emptied.
EventQueue mEventQueue;
EventQueueSized<64> mEventQueue;
// The event target we dispatch our events (actually, just our Executor) to.
//