зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
ede385148e
Коммит
6835880244
|
@ -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.
|
||||
//
|
||||
|
|
Загрузка…
Ссылка в новой задаче