Bug 1151656 - Implement the ability to assert tail dispatch. r=mattwoodrow

In order to make sure that the MDSM properly dispatches everything via tail
dispatch, we want verification that is more robust than simple inspection.
This commit is contained in:
Bobby Holley 2015-04-07 11:44:10 -07:00
parent 9efc9ef1b1
commit 6b696acdb9
3 changed files with 37 additions and 2 deletions

View File

@ -20,6 +20,7 @@ template<>
nsresult
AbstractThreadImpl<nsIThread>::Dispatch(already_AddRefed<nsIRunnable> aRunnable)
{
MediaTaskQueue::AssertInTailDispatchIfNeeded();
nsCOMPtr<nsIRunnable> r = aRunnable;
return mTarget->Dispatch(r, NS_DISPATCH_NORMAL);
}

View File

@ -20,13 +20,15 @@ MediaTaskQueue::InitStatics()
}
}
MediaTaskQueue::MediaTaskQueue(TemporaryRef<SharedThreadPool> aPool)
MediaTaskQueue::MediaTaskQueue(TemporaryRef<SharedThreadPool> aPool,
bool aRequireTailDispatch)
: mPool(aPool)
, mQueueMonitor("MediaTaskQueue::Queue")
, mTailDispatcher(nullptr)
, mIsRunning(false)
, mIsShutdown(false)
, mIsFlushing(false)
, mRequireTailDispatch(aRequireTailDispatch)
{
MOZ_COUNT_CTOR(MediaTaskQueue);
}
@ -41,6 +43,7 @@ MediaTaskQueue::~MediaTaskQueue()
nsresult
MediaTaskQueue::Dispatch(TemporaryRef<nsIRunnable> aRunnable)
{
AssertInTailDispatchIfNeeded(); // Do this before acquiring the monitor.
MonitorAutoLock mon(mQueueMonitor);
return DispatchLocked(aRunnable, AbortIfFlushing);
}
@ -56,6 +59,7 @@ MediaTaskQueue::TailDispatcher()
nsresult
MediaTaskQueue::ForceDispatch(TemporaryRef<nsIRunnable> aRunnable)
{
AssertInTailDispatchIfNeeded(); // Do this before acquiring the monitor.
MonitorAutoLock mon(mQueueMonitor);
return DispatchLocked(aRunnable, Forced);
}
@ -178,6 +182,7 @@ FlushableMediaTaskQueue::Flush()
nsresult
FlushableMediaTaskQueue::FlushAndDispatch(TemporaryRef<nsIRunnable> aRunnable)
{
AssertInTailDispatchIfNeeded(); // Do this before acquiring the monitor.
MonitorAutoLock mon(mQueueMonitor);
AutoSetFlushing autoFlush(this);
FlushLocked();

View File

@ -38,7 +38,7 @@ public:
// if the caller is not running in a MediaTaskQueue.
static MediaTaskQueue* GetCurrentQueue() { return sCurrentQueueTLS.get(); }
explicit MediaTaskQueue(TemporaryRef<SharedThreadPool> aPool);
explicit MediaTaskQueue(TemporaryRef<SharedThreadPool> aPool, bool aRequireTailDispatch = false);
nsresult Dispatch(TemporaryRef<nsIRunnable> aRunnable);
@ -48,6 +48,31 @@ public:
// May only be called when running within the task queue it is invoked up.
TaskDispatcher& TailDispatcher();
// Returns true if this task queue requires all dispatches performed by its
// tasks to go through the tail dispatcher.
bool RequiresTailDispatch() { return mRequireTailDispatch; }
#ifdef DEBUG
static void AssertInTailDispatchIfNeeded()
{
// See if we're currently running in a task queue that asserts tail
// dispatch.
MediaTaskQueue* currentQueue = MediaTaskQueue::GetCurrentQueue();
if (!currentQueue || !currentQueue->RequiresTailDispatch()) {
return;
}
// This is a bit tricky. The only moment when we're running in a task queue
// but don't have mTailDispatcher set is precisely the moment that we're
// doing tail dispatch (i.e. when AutoTaskGuard's destructor has already
// run and AutoTaskDispatcher's destructor is currently running).
MOZ_ASSERT(!currentQueue->mTailDispatcher,
"Not allowed to dispatch tasks directly from this task queue - use TailDispatcher()");
}
#else
static void AssertInTailDispatchIfNeeded() {}
#endif
// For AbstractThread.
nsresult Dispatch(already_AddRefed<nsIRunnable> aRunnable) override
{
@ -157,6 +182,10 @@ protected:
// True if we're flushing; we reject new tasks if we're flushing.
bool mIsFlushing;
// True if we want to require that every task dispatched from tasks running in
// this queue go through our queue's tail dispatcher.
bool mRequireTailDispatch;
class Runner : public nsRunnable {
public:
explicit Runner(MediaTaskQueue* aQueue)