Bug 1552958 - De-templatize PrioritizedEventQueue, r=froydnj
authorOlli Pettay <Olli.Pettay@helsinki.fi>
Tue, 21 May 2019 18:20:34 +0000
changeset 474815 257f2c96cef502a1d674df56c8e39d76d8ed4d89
parent 474814 f023603f7e7265c5602fb6e9c871b19a3c7f3a92
child 474816 fb696b92c13dfcc10af3c528c013e3d513510c12
child 474915 d3280055a40ef72f1fe8be1c6352bbe5469c15e0
push id36046
push useraiakab@mozilla.com
push dateTue, 21 May 2019 21:45:52 +0000
treeherdermozilla-central@257f2c96cef5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs1552958
milestone69.0a1
first release with
nightly linux32
257f2c96cef5 / 69.0a1 / 20190521214552 / files
nightly linux64
257f2c96cef5 / 69.0a1 / 20190521214552 / files
nightly mac
257f2c96cef5 / 69.0a1 / 20190521214552 / files
nightly win32
257f2c96cef5 / 69.0a1 / 20190521214552 / files
nightly win64
257f2c96cef5 / 69.0a1 / 20190521214552 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1552958 - De-templatize PrioritizedEventQueue, r=froydnj PrioritizedEventQueue's template is always EventQueue, so the template argument is rather useless. Trying to keep the patch minimal, so CreateMainThread for example is still a bit weird. Differential Revision: https://phabricator.services.mozilla.com/D31871
xpcom/threads/MainThreadQueue.h
xpcom/threads/PrioritizedEventQueue.cpp
xpcom/threads/PrioritizedEventQueue.h
xpcom/threads/ThreadEventQueue.cpp
xpcom/threads/ThreadEventQueue.h
xpcom/threads/nsThreadManager.cpp
--- a/xpcom/threads/MainThreadQueue.h
+++ b/xpcom/threads/MainThreadQueue.h
@@ -11,21 +11,21 @@
 #include "mozilla/EventQueue.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/UniquePtr.h"
 #include "nsThread.h"
 #include "PrioritizedEventQueue.h"
 
 namespace mozilla {
 
-template <typename SynchronizedQueueT, typename InnerQueueT>
+template <typename SynchronizedQueueT>
 inline already_AddRefed<nsThread> CreateMainThread(
     nsIIdlePeriod* aIdlePeriod,
     SynchronizedQueueT** aSynchronizedQueue = nullptr) {
-  using MainThreadQueueT = PrioritizedEventQueue<InnerQueueT>;
+  using MainThreadQueueT = PrioritizedEventQueue;
 
   auto queue = MakeUnique<MainThreadQueueT>(do_AddRef(aIdlePeriod));
 
   MainThreadQueueT* prioritized = queue.get();
 
   RefPtr<SynchronizedQueueT> synchronizedQueue =
       new SynchronizedQueueT(std::move(queue));
 
--- a/xpcom/threads/PrioritizedEventQueue.cpp
+++ b/xpcom/threads/PrioritizedEventQueue.cpp
@@ -9,22 +9,19 @@
 #include "mozilla/ScopeExit.h"
 #include "mozilla/StaticPrefs.h"
 #include "nsThreadManager.h"
 #include "nsXPCOMPrivate.h"  // for gXPCOMThreadsShutDown
 #include "InputEventStatistics.h"
 
 using namespace mozilla;
 
-template <class InnerQueueT>
-void PrioritizedEventQueue<InnerQueueT>::PutEvent(
+void PrioritizedEventQueue::PutEvent(
     already_AddRefed<nsIRunnable>&& aEvent, EventQueuePriority aPriority,
     const MutexAutoLock& aProofOfLock) {
-  static_assert(IsBaseOf<AbstractEventQueue, InnerQueueT>::value,
-                "InnerQueueT must be an AbstractEventQueue subclass");
 
   // Double check the priority with a QI.
   RefPtr<nsIRunnable> event(aEvent);
   EventQueuePriority priority = aPriority;
 
   if (priority == EventQueuePriority::Input &&
       mInputQueueState == STATE_DISABLED) {
     priority = EventQueuePriority::Normal;
@@ -53,18 +50,17 @@ void PrioritizedEventQueue<InnerQueueT>:
       mIdleQueue->PutEvent(event.forget(), priority, aProofOfLock);
       break;
     case EventQueuePriority::Count:
       MOZ_CRASH("EventQueuePriority::Count isn't a valid priority");
       break;
   }
 }
 
-template <class InnerQueueT>
-TimeStamp PrioritizedEventQueue<InnerQueueT>::GetIdleDeadline() {
+TimeStamp PrioritizedEventQueue::GetIdleDeadline() {
   // If we are shutting down, we won't honor the idle period, and we will
   // always process idle runnables.  This will ensure that the idle queue
   // gets exhausted at shutdown time to prevent intermittently leaking
   // some runnables inside that queue and even worse potentially leaving
   // some important cleanup work unfinished.
   if (gXPCOMThreadsShutDown ||
       nsThreadManager::get().GetCurrentThread()->ShuttingDown()) {
     return TimeStamp::Now();
@@ -99,18 +95,17 @@ TimeStamp PrioritizedEventQueue<InnerQue
     // If HasPendingEvents() has been called and it has returned true, but we're
     // no longer in the idle period, we must return a valid timestamp to pretend
     // that we are still in the idle period.
     return TimeStamp::Now();
   }
   return idleDeadline;
 }
 
-template <class InnerQueueT>
-EventQueuePriority PrioritizedEventQueue<InnerQueueT>::SelectQueue(
+EventQueuePriority PrioritizedEventQueue::SelectQueue(
     bool aUpdateState, const MutexAutoLock& aProofOfLock) {
   size_t inputCount = mInputQueue->Count(aProofOfLock);
 
   if (aUpdateState && mInputQueueState == STATE_ENABLED &&
       mInputHandlingStartTime.IsNull() && inputCount > 0) {
     mInputHandlingStartTime =
         InputEventStatistics::Get().GetInputHandlingStartTime(inputCount);
   }
@@ -176,18 +171,17 @@ EventQueuePriority PrioritizedEventQueue
 
   if (aUpdateState) {
     mProcessHighPriorityQueue = highPending;
   }
 
   return queue;
 }
 
-template <class InnerQueueT>
-already_AddRefed<nsIRunnable> PrioritizedEventQueue<InnerQueueT>::GetEvent(
+already_AddRefed<nsIRunnable> PrioritizedEventQueue::GetEvent(
     EventQueuePriority* aPriority, const MutexAutoLock& aProofOfLock) {
   auto guard =
       MakeScopeExit([&] { mHasPendingEventsPromisedIdleEvent = false; });
 
 #ifndef RELEASE_OR_BETA
   // Clear mNextIdleDeadline so that it is possible to determine that
   // we're running an idle runnable in ProcessNextEvent.
   *mNextIdleDeadline = TimeStamp();
@@ -257,31 +251,29 @@ already_AddRefed<nsIRunnable> Prioritize
     // in ProcessNextEvent.
     *mNextIdleDeadline = idleDeadline;
 #endif
   }
 
   return event.forget();
 }
 
-template <class InnerQueueT>
-bool PrioritizedEventQueue<InnerQueueT>::IsEmpty(
+bool PrioritizedEventQueue::IsEmpty(
     const MutexAutoLock& aProofOfLock) {
   // Just check IsEmpty() on the sub-queues. Don't bother checking the idle
   // deadline since that only determines whether an idle event is ready or not.
   return mHighQueue->IsEmpty(aProofOfLock) &&
          mInputQueue->IsEmpty(aProofOfLock) &&
          mMediumHighQueue->IsEmpty(aProofOfLock) &&
          mNormalQueue->IsEmpty(aProofOfLock) &&
          mDeferredTimersQueue->IsEmpty(aProofOfLock) &&
          mIdleQueue->IsEmpty(aProofOfLock);
 }
 
-template <class InnerQueueT>
-bool PrioritizedEventQueue<InnerQueueT>::HasReadyEvent(
+bool PrioritizedEventQueue::HasReadyEvent(
     const MutexAutoLock& aProofOfLock) {
   mHasPendingEventsPromisedIdleEvent = false;
 
   EventQueuePriority queue = SelectQueue(false, aProofOfLock);
 
   if (queue == EventQueuePriority::High) {
     return mHighQueue->HasReadyEvent(aProofOfLock);
   } else if (queue == EventQueuePriority::Input) {
@@ -307,55 +299,45 @@ bool PrioritizedEventQueue<InnerQueueT>:
                        mIdleQueue->HasReadyEvent(aProofOfLock))) {
     mHasPendingEventsPromisedIdleEvent = true;
     return true;
   }
 
   return false;
 }
 
-template <class InnerQueueT>
-bool PrioritizedEventQueue<InnerQueueT>::HasPendingHighPriorityEvents(
+bool PrioritizedEventQueue::HasPendingHighPriorityEvents(
     const MutexAutoLock& aProofOfLock) {
   return !mHighQueue->IsEmpty(aProofOfLock);
 }
 
-template <class InnerQueueT>
-size_t PrioritizedEventQueue<InnerQueueT>::Count(
+size_t PrioritizedEventQueue::Count(
     const MutexAutoLock& aProofOfLock) const {
   MOZ_CRASH("unimplemented");
 }
 
-template <class InnerQueueT>
-void PrioritizedEventQueue<InnerQueueT>::EnableInputEventPrioritization(
+void PrioritizedEventQueue::EnableInputEventPrioritization(
     const MutexAutoLock& aProofOfLock) {
   MOZ_ASSERT(mInputQueueState == STATE_DISABLED);
   mInputQueueState = STATE_ENABLED;
   mInputHandlingStartTime = TimeStamp();
 }
 
-template <class InnerQueueT>
-void PrioritizedEventQueue<InnerQueueT>::FlushInputEventPrioritization(
+void PrioritizedEventQueue::FlushInputEventPrioritization(
     const MutexAutoLock& aProofOfLock) {
   MOZ_ASSERT(mInputQueueState == STATE_ENABLED ||
              mInputQueueState == STATE_SUSPEND);
   mInputQueueState =
       mInputQueueState == STATE_ENABLED ? STATE_FLUSHING : STATE_SUSPEND;
 }
 
-template <class InnerQueueT>
-void PrioritizedEventQueue<InnerQueueT>::SuspendInputEventPrioritization(
+void PrioritizedEventQueue::SuspendInputEventPrioritization(
     const MutexAutoLock& aProofOfLock) {
   MOZ_ASSERT(mInputQueueState == STATE_ENABLED ||
              mInputQueueState == STATE_FLUSHING);
   mInputQueueState = STATE_SUSPEND;
 }
 
-template <class InnerQueueT>
-void PrioritizedEventQueue<InnerQueueT>::ResumeInputEventPrioritization(
+void PrioritizedEventQueue::ResumeInputEventPrioritization(
     const MutexAutoLock& aProofOfLock) {
   MOZ_ASSERT(mInputQueueState == STATE_SUSPEND);
   mInputQueueState = STATE_ENABLED;
 }
-
-namespace mozilla {
-template class PrioritizedEventQueue<EventQueue>;
-}  // namespace mozilla
--- a/xpcom/threads/PrioritizedEventQueue.h
+++ b/xpcom/threads/PrioritizedEventQueue.h
@@ -3,16 +3,17 @@
 /* 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_PrioritizedEventQueue_h
 #define mozilla_PrioritizedEventQueue_h
 
 #include "mozilla/AbstractEventQueue.h"
+#include "mozilla/EventQueue.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/TypeTraits.h"
 #include "mozilla/UniquePtr.h"
 #include "nsCOMPtr.h"
 #include "nsIIdlePeriod.h"
 
 class nsIRunnable;
 
@@ -30,30 +31,29 @@ namespace mozilla {
 // optimize for performance. Roughly, events are selected from the highest
 // priority queue that is non-empty. However, there are a few exceptions:
 // - We try to avoid processing too many high-priority events in a row so
 //   that the normal priority queue is not starved. When there are high-
 //   and normal-priority events available, we interleave popping from the
 //   normal and high queues.
 // - We do not select events from the idle queue if the current idle period
 //   is almost over.
-template <class InnerQueueT>
 class PrioritizedEventQueue final : public AbstractEventQueue {
  public:
   static const bool SupportsPrioritization = true;
 
   explicit PrioritizedEventQueue(already_AddRefed<nsIIdlePeriod> aIdlePeriod)
-      : mHighQueue(MakeUnique<InnerQueueT>(EventQueuePriority::High)),
-        mInputQueue(MakeUnique<InnerQueueT>(EventQueuePriority::Input)),
+      : mHighQueue(MakeUnique<EventQueue>(EventQueuePriority::High)),
+        mInputQueue(MakeUnique<EventQueue>(EventQueuePriority::Input)),
         mMediumHighQueue(
-            MakeUnique<InnerQueueT>(EventQueuePriority::MediumHigh)),
-        mNormalQueue(MakeUnique<InnerQueueT>(EventQueuePriority::Normal)),
+            MakeUnique<EventQueue>(EventQueuePriority::MediumHigh)),
+        mNormalQueue(MakeUnique<EventQueue>(EventQueuePriority::Normal)),
         mDeferredTimersQueue(
-            MakeUnique<InnerQueueT>(EventQueuePriority::DeferredTimers)),
-        mIdleQueue(MakeUnique<InnerQueueT>(EventQueuePriority::Idle)),
+            MakeUnique<EventQueue>(EventQueuePriority::DeferredTimers)),
+        mIdleQueue(MakeUnique<EventQueue>(EventQueuePriority::Idle)),
         mIdlePeriod(aIdlePeriod) {}
 
   void PutEvent(already_AddRefed<nsIRunnable>&& aEvent,
                 EventQueuePriority aPriority,
                 const MutexAutoLock& aProofOfLock) final;
   already_AddRefed<nsIRunnable> GetEvent(
       EventQueuePriority* aPriority, const MutexAutoLock& aProofOfLock) final;
 
@@ -102,22 +102,22 @@ class PrioritizedEventQueue final : publ
 
  private:
   EventQueuePriority SelectQueue(bool aUpdateState,
                                  const MutexAutoLock& aProofOfLock);
 
   // Returns a null TimeStamp if we're not in the idle period.
   mozilla::TimeStamp GetIdleDeadline();
 
-  UniquePtr<InnerQueueT> mHighQueue;
-  UniquePtr<InnerQueueT> mInputQueue;
-  UniquePtr<InnerQueueT> mMediumHighQueue;
-  UniquePtr<InnerQueueT> mNormalQueue;
-  UniquePtr<InnerQueueT> mDeferredTimersQueue;
-  UniquePtr<InnerQueueT> mIdleQueue;
+  UniquePtr<EventQueue> mHighQueue;
+  UniquePtr<EventQueue> mInputQueue;
+  UniquePtr<EventQueue> mMediumHighQueue;
+  UniquePtr<EventQueue> mNormalQueue;
+  UniquePtr<EventQueue> mDeferredTimersQueue;
+  UniquePtr<EventQueue> mIdleQueue;
 
   // We need to drop the queue mutex when checking the idle deadline, so we keep
   // a pointer to it here.
   Mutex* mMutex = nullptr;
 
 #ifndef RELEASE_OR_BETA
   // Pointer to a place where the most recently computed idle deadline is
   // stored.
@@ -147,14 +147,11 @@ class PrioritizedEventQueue final : publ
     STATE_DISABLED,
     STATE_FLUSHING,
     STATE_SUSPEND,
     STATE_ENABLED
   };
   InputEventQueueState mInputQueueState = STATE_DISABLED;
 };
 
-class EventQueue;
-extern template class PrioritizedEventQueue<EventQueue>;
-
 }  // namespace mozilla
 
 #endif  // mozilla_PrioritizedEventQueue_h
--- a/xpcom/threads/ThreadEventQueue.cpp
+++ b/xpcom/threads/ThreadEventQueue.cpp
@@ -289,10 +289,10 @@ ThreadEventQueue<InnerQueueT>::GetObserv
 template <class InnerQueueT>
 void ThreadEventQueue<InnerQueueT>::SetObserver(nsIThreadObserver* aObserver) {
   MutexAutoLock lock(mLock);
   mObserver = aObserver;
 }
 
 namespace mozilla {
 template class ThreadEventQueue<EventQueue>;
-template class ThreadEventQueue<PrioritizedEventQueue<EventQueue>>;
+template class ThreadEventQueue<PrioritizedEventQueue>;
 }  // namespace mozilla
--- a/xpcom/threads/ThreadEventQueue.h
+++ b/xpcom/threads/ThreadEventQueue.h
@@ -15,20 +15,17 @@
 
 class nsIEventTarget;
 class nsISerialEventTarget;
 class nsIThreadObserver;
 
 namespace mozilla {
 
 class EventQueue;
-
-template <typename InnerQueueT>
 class PrioritizedEventQueue;
-
 class ThreadEventTarget;
 
 // A ThreadEventQueue implements normal monitor-style synchronization over the
 // InnerQueueT AbstractEventQueue. It also implements PushEventQueue and
 // PopEventQueue for workers (see the documentation below for an explanation of
 // those). All threads use a ThreadEventQueue as their event queue. InnerQueueT
 // is a template parameter to avoid virtual dispatch overhead.
 template <class InnerQueueT>
@@ -89,13 +86,13 @@ class ThreadEventQueue final : public Sy
   Mutex mLock;
   CondVar mEventsAvailable;
 
   bool mEventsAreDoomed = false;
   nsCOMPtr<nsIThreadObserver> mObserver;
 };
 
 extern template class ThreadEventQueue<EventQueue>;
-extern template class ThreadEventQueue<PrioritizedEventQueue<EventQueue>>;
+extern template class ThreadEventQueue<PrioritizedEventQueue>;
 
 };  // namespace mozilla
 
 #endif  // mozilla_ThreadEventQueue_h
--- a/xpcom/threads/nsThreadManager.cpp
+++ b/xpcom/threads/nsThreadManager.cpp
@@ -218,18 +218,17 @@ nsresult nsThreadManager::Init() {
       env_var_flag
           ? (env_var_flag[0] ? open(env_var_flag, flags, mode) : STDERR_FILENO)
           : 0;
 #endif
 
   nsCOMPtr<nsIIdlePeriod> idlePeriod = new MainThreadIdlePeriod();
 
   mMainThread =
-      CreateMainThread<ThreadEventQueue<PrioritizedEventQueue<EventQueue>>,
-                       EventQueue>(idlePeriod);
+      CreateMainThread<ThreadEventQueue<PrioritizedEventQueue>>(idlePeriod);
 
   nsresult rv = mMainThread->InitCurrentThread();
   if (NS_FAILED(rv)) {
     mMainThread = nullptr;
     return rv;
   }
 
   // We need to keep a pointer to the current thread, so we can satisfy