Bug 1269963 - Add a SyncRunnable::DispatchToThread() overload for AbstractThread. r=bobbyholley.
MozReview-Commit-ID: Jog4glNrUHw
--- 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);