Bug 1368358 - ThrottledEventQueue::Inner::IsOnCurrentThread should work similarly to other IsOnCurrentThread implementations, r=bkelly
--- a/xpcom/threads/ThrottledEventQueue.cpp
+++ b/xpcom/threads/ThrottledEventQueue.cpp
@@ -91,29 +91,25 @@ class ThrottledEventQueue::Inner final :
nsEventQueue mEventQueue;
// written on main thread, read on any thread
nsCOMPtr<nsIEventTarget> mBaseTarget;
// any thread, protected by mutex
nsCOMPtr<nsIRunnable> mExecutor;
- // any thread, atomic
- Atomic<uint32_t> mExecutionDepth;
-
// any thread, protected by mutex
bool mShutdownStarted;
explicit Inner(nsIEventTarget* aBaseTarget)
: mMutex("ThrottledEventQueue")
, mIdleCondVar(mMutex, "ThrottledEventQueue:Idle")
, mEventsAvailable(mMutex, "[ThrottledEventQueue::Inner.mEventsAvailable]")
, mEventQueue(mEventsAvailable, nsEventQueue::eNormalQueue)
, mBaseTarget(aBaseTarget)
- , mExecutionDepth(0)
, mShutdownStarted(false)
{
}
~Inner()
{
MOZ_ASSERT(!mExecutor);
MOZ_ASSERT(mShutdownStarted);
@@ -134,22 +130,17 @@ class ThrottledEventQueue::Inner final :
MutexAutoLock lock(mMutex);
// We only check the name of an executor runnable when we know there is something
// in the queue, so this should never fail.
MOZ_ALWAYS_TRUE(mEventQueue.PeekEvent(getter_AddRefs(event), lock));
}
if (nsCOMPtr<nsINamed> named = do_QueryInterface(event)) {
- // Increase mExecutionDepth here so that GetName is allowed to call
- // IsOnCurrentThread on us and have it be true (in the case when we are on
- // the right thread).
- mExecutionDepth++;
nsresult rv = named->GetName(aName);
- mExecutionDepth--;
return rv;
}
aName.AssignLiteral("non-nsINamed ThrottledEventQueue runnable");
return NS_OK;
}
void
@@ -191,19 +182,17 @@ class ThrottledEventQueue::Inner final :
shouldShutdown = mShutdownStarted;
// Note, this breaks a ref cycle.
mExecutor = nullptr;
mIdleCondVar.NotifyAll();
}
}
// Execute the event now that we have unlocked.
- ++mExecutionDepth;
Unused << event->Run();
- --mExecutionDepth;
// If shutdown was started and the queue is now empty we can now
// finalize the shutdown. This is performed separately at the end
// of the method in order to wait for the event to finish running.
if (shouldShutdown) {
MOZ_ASSERT(IsEmpty());
NS_DispatchToMainThread(NewRunnableMethod("ThrottledEventQueue::Inner::ShutdownComplete",
this, &Inner::ShutdownComplete));
@@ -372,37 +361,17 @@ public:
// The base target may implement this, but we don't. Always fail
// to provide consistent behavior.
return NS_ERROR_NOT_IMPLEMENTED;
}
nsresult
IsOnCurrentThread(bool* aResult)
{
- // Any thread
-
- bool shutdownAndIdle = false;
- {
- MutexAutoLock lock(mMutex);
- shutdownAndIdle = mShutdownStarted && mEventQueue.Count(lock) == 0;
- }
-
- bool onBaseTarget = false;
- nsresult rv = mBaseTarget->IsOnCurrentThread(&onBaseTarget);
- if (NS_FAILED(rv)) {
- return rv;
- }
-
- // We consider the current stack on this event target if are on
- // the base target and one of the following is true
- // 1) We are currently running an event OR
- // 2) We are both shutting down and the queue is idle
- *aResult = onBaseTarget && (mExecutionDepth || shutdownAndIdle);
-
- return NS_OK;
+ return mBaseTarget->IsOnCurrentThread(aResult);
}
NS_DECL_THREADSAFE_ISUPPORTS
};
NS_IMPL_ISUPPORTS(ThrottledEventQueue::Inner, nsIObserver);
NS_IMPL_ISUPPORTS(ThrottledEventQueue, ThrottledEventQueue, nsIEventTarget);