Bug 1154805 - Do tail dispatch automatically. r=jww
authorBobby Holley <bobbyholley@gmail.com>
Wed, 15 Apr 2015 10:54:25 -0700
changeset 239613 243c4d6debc967071451cdc06fa61efd6c429d9b
parent 239612 b07c9579cde5fe3b4a319abadbbcf54fd1abc1fd
child 239614 26392bfd1bc137cc6eca73534c0ebbf965440b2e
push id12444
push userryanvm@gmail.com
push dateFri, 17 Apr 2015 20:04:42 +0000
treeherderfx-team@560a202db924 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjww
bugs1154805
milestone40.0a1
Bug 1154805 - Do tail dispatch automatically. r=jww
dom/media/AbstractThread.cpp
dom/media/AbstractThread.h
dom/media/MediaTaskQueue.cpp
dom/media/MediaTaskQueue.h
--- a/dom/media/AbstractThread.cpp
+++ b/dom/media/AbstractThread.cpp
@@ -25,18 +25,23 @@ public:
     : AbstractThread(/* aRequireTailDispatch = */ false)
     , mTarget(aTarget)
   {}
 
   virtual void Dispatch(already_AddRefed<nsIRunnable> aRunnable,
                         DispatchFailureHandling aFailureHandling = AssertDispatchSuccess,
                         DispatchReason aReason = NormalDispatch) override
   {
-    MOZ_ASSERT_IF(aReason != TailDispatch, !CurrentThreadRequiresTailDispatch());
     nsCOMPtr<nsIRunnable> r = aRunnable;
+    AbstractThread* currentThread;
+    if (aReason != TailDispatch && (currentThread = GetCurrent()) && currentThread->RequiresTailDispatch()) {
+      currentThread->TailDispatcher().AddTask(this, r.forget(), aFailureHandling);
+      return;
+    }
+
     nsresult rv = mTarget->Dispatch(r, NS_DISPATCH_NORMAL);
     MOZ_DIAGNOSTIC_ASSERT(aFailureHandling == DontAssertDispatchSuccess || NS_SUCCEEDED(rv));
     unused << rv;
   }
 
   virtual bool IsCurrentThreadIn() override
   {
     bool in = NS_GetCurrentThread() == mTarget;
--- a/dom/media/AbstractThread.h
+++ b/dom/media/AbstractThread.h
@@ -75,24 +75,16 @@ public:
   bool RequiresTailDispatch() const { return mRequireTailDispatch; }
 
   // Convenience method for getting an AbstractThread for the main thread.
   static AbstractThread* MainThread();
 
   // Must be called exactly once during startup.
   static void InitStatics();
 
-  // Returns true if the currently-running thread is an AbstractThread that
-  // requires tail dispatch.
-  static bool CurrentThreadRequiresTailDispatch()
-  {
-    AbstractThread* current = GetCurrent();
-    return current && current->RequiresTailDispatch();
-  }
-
 protected:
   virtual ~AbstractThread() {}
   static ThreadLocal<AbstractThread*> sCurrentThreadTLS;
 
   // True if we want to require that every task dispatched from tasks running in
   // this queue go through our queue's tail dispatcher.
   const bool mRequireTailDispatch;
 };
--- a/dom/media/MediaTaskQueue.cpp
+++ b/dom/media/MediaTaskQueue.cpp
@@ -35,21 +35,27 @@ MediaTaskQueue::TailDispatcher()
 {
   MOZ_ASSERT(IsCurrentThreadIn());
   MOZ_ASSERT(mTailDispatcher);
   return *mTailDispatcher;
 }
 
 nsresult
 MediaTaskQueue::DispatchLocked(already_AddRefed<nsIRunnable> aRunnable,
-                               DispatchMode aMode, DispatchReason aReason)
+                               DispatchMode aMode, DispatchFailureHandling aFailureHandling,
+                               DispatchReason aReason)
 {
-  MOZ_ASSERT_IF(aReason != TailDispatch, !CurrentThreadRequiresTailDispatch());
+  nsCOMPtr<nsIRunnable> r = aRunnable;
+  AbstractThread* currentThread;
+  if (aReason != TailDispatch && (currentThread = GetCurrent()) && currentThread->RequiresTailDispatch()) {
+    currentThread->TailDispatcher().AddTask(this, r.forget(), aFailureHandling);
+    return NS_OK;
+  }
+
   mQueueMonitor.AssertCurrentThreadOwns();
-  nsCOMPtr<nsIRunnable> r = aRunnable;
   if (mIsFlushing && aMode == AbortIfFlushing) {
     return NS_ERROR_ABORT;
   }
   if (mIsShutdown) {
     return NS_ERROR_FAILURE;
   }
   mTasks.push(r.forget());
   if (mIsRunning) {
@@ -156,17 +162,17 @@ FlushableMediaTaskQueue::Flush()
 
 nsresult
 FlushableMediaTaskQueue::FlushAndDispatch(TemporaryRef<nsIRunnable> aRunnable)
 {
   MonitorAutoLock mon(mQueueMonitor);
   AutoSetFlushing autoFlush(this);
   FlushLocked();
   nsCOMPtr<nsIRunnable> r = dont_AddRef(aRunnable.take());
-  nsresult rv = DispatchLocked(r.forget(), IgnoreFlushing);
+  nsresult rv = DispatchLocked(r.forget(), IgnoreFlushing, AssertDispatchSuccess);
   NS_ENSURE_SUCCESS(rv, rv);
   AwaitIdleLocked();
   return NS_OK;
 }
 
 void
 FlushableMediaTaskQueue::FlushLocked()
 {
--- a/dom/media/MediaTaskQueue.h
+++ b/dom/media/MediaTaskQueue.h
@@ -42,17 +42,17 @@ public:
 
   TaskDispatcher& TailDispatcher() override;
 
   void Dispatch(already_AddRefed<nsIRunnable> aRunnable,
                 DispatchFailureHandling aFailureHandling = AssertDispatchSuccess,
                 DispatchReason aReason = NormalDispatch) override
   {
     MonitorAutoLock mon(mQueueMonitor);
-    nsresult rv = DispatchLocked(Move(aRunnable), AbortIfFlushing, aReason);
+    nsresult rv = DispatchLocked(Move(aRunnable), AbortIfFlushing, aFailureHandling, aReason);
     MOZ_DIAGNOSTIC_ASSERT(aFailureHandling == DontAssertDispatchSuccess || NS_SUCCEEDED(rv));
     unused << rv;
   }
 
   // DEPRECATED! Do not us, if a flush happens at the same time, this function
   // can hang and block forever!
   void SyncDispatch(TemporaryRef<nsIRunnable> aRunnable);
 
@@ -95,16 +95,17 @@ protected:
   // Blocks until all task finish executing. Called internally by methods
   // that need to wait until the task queue is idle.
   // mQueueMonitor must be held.
   void AwaitIdleLocked();
 
   enum DispatchMode { AbortIfFlushing, IgnoreFlushing };
 
   nsresult DispatchLocked(already_AddRefed<nsIRunnable> aRunnable, DispatchMode aMode,
+                          DispatchFailureHandling aFailureHandling,
                           DispatchReason aReason = NormalDispatch);
 
   RefPtr<SharedThreadPool> mPool;
 
   // Monitor that protects the queue and mIsRunning;
   Monitor mQueueMonitor;
 
   // Queue of tasks to run.