Bug 1269963 - Add a SyncRunnable::DispatchToThread() overload for AbstractThread. r=bobbyholley. draft
authorJW Wang <jwwang@mozilla.com>
Wed, 04 May 2016 16:24:25 +0800
changeset 363233 52dd4792c754a8514a9c932c48a0a72e6e2aa473
parent 363232 13054350512c010fd207d136c576559a11b092b5
child 519982 18166622b2aa07731e107580a4393b592055c35c
push id17145
push userjwwang@mozilla.com
push dateWed, 04 May 2016 09:08:24 +0000
reviewersbobbyholley
bugs1269963
milestone49.0a1
Bug 1269963 - Add a SyncRunnable::DispatchToThread() overload for AbstractThread. r=bobbyholley. MozReview-Commit-ID: Jog4glNrUHw
xpcom/threads/AbstractThread.cpp
xpcom/threads/SyncRunnable.h
--- a/xpcom/threads/AbstractThread.cpp
+++ b/xpcom/threads/AbstractThread.cpp
@@ -102,17 +102,17 @@ private:
   Maybe<AutoTaskDispatcher> mTailDispatcher;
 };
 
 bool
 AbstractThread::RequiresTailDispatch(AbstractThread* aThread) const
 {
   // We require tail dispatch if both the source and destination
   // threads support it.
-  return SupportsTailDispatch() && aThread->SupportsTailDispatch();
+  return SupportsTailDispatch() && aThread && aThread->SupportsTailDispatch();
 }
 
 AbstractThread*
 AbstractThread::MainThread()
 {
   MOZ_ASSERT(sMainThread);
   return sMainThread;
 }
--- a/xpcom/threads/SyncRunnable.h
+++ b/xpcom/threads/SyncRunnable.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_SyncRunnable_h
 #define mozilla_SyncRunnable_h
 
 #include "nsThreadUtils.h"
+#include "mozilla/AbstractThread.h"
 #include "mozilla/Monitor.h"
 
 namespace mozilla {
 
 /**
  * This class will wrap a nsIRunnable and dispatch it to the main thread
  * synchronously. This is different from nsIEventTarget.DISPATCH_SYNC:
  * this class does not spin the event loop waiting for the event to be
@@ -56,24 +57,50 @@ public:
     if (NS_SUCCEEDED(rv)) {
       mozilla::MonitorAutoLock lock(mMonitor);
       while (!mDone) {
         lock.Wait();
       }
     }
   }
 
+  void DispatchToThread(AbstractThread* aThread, bool aForceDispatch = false)
+  {
+    if (!aForceDispatch && aThread->IsCurrentThreadIn()) {
+      mRunnable->Run();
+      return;
+    }
+
+    // Check we don't have tail dispatching here. Otherwise we will deadlock
+    // ourself when spinning the loop below.
+    MOZ_ASSERT(!aThread->RequiresTailDispatch(AbstractThread::GetCurrent()));
+
+    aThread->Dispatch(RefPtr<nsIRunnable>(this).forget());
+    mozilla::MonitorAutoLock lock(mMonitor);
+    while (!mDone) {
+      lock.Wait();
+    }
+  }
+
   static void DispatchToThread(nsIEventTarget* aThread,
                                nsIRunnable* aRunnable,
                                bool aForceDispatch = false)
   {
     RefPtr<SyncRunnable> s(new SyncRunnable(aRunnable));
     s->DispatchToThread(aThread, aForceDispatch);
   }
 
+  static void DispatchToThread(AbstractThread* aThread,
+                               nsIRunnable* aRunnable,
+                               bool aForceDispatch = false)
+  {
+    RefPtr<SyncRunnable> s(new SyncRunnable(aRunnable));
+    s->DispatchToThread(aThread, aForceDispatch);
+  }
+
 protected:
   NS_IMETHODIMP Run()
   {
     mRunnable->Run();
 
     mozilla::MonitorAutoLock lock(mMonitor);
     MOZ_ASSERT(!mDone);