Bug 1154782 - Remove the concept of forced dispatch. r=jww

I added this several months ago to make MediaPromise dispatch reliable in the
presence of the god-awful Flush() feature of MediaTaskQueue. That feature has
now been restricted to a special subclass (which we should eventually eliminate),
so we can just assert that MediaPromises are never used on those task queues
and simplify the rest of the code.
This commit is contained in:
Bobby Holley 2015-04-14 17:47:22 -07:00
parent 5e5e97cbb7
commit 5c97f72557
4 changed files with 16 additions and 33 deletions

View File

@ -43,6 +43,10 @@ public:
void MaybeTailDispatch(already_AddRefed<nsIRunnable> aRunnable,
DispatchFailureHandling aFailureHandling = AssertDispatchSuccess);
// Returns true if dispatch is generally reliable. This is used to guard
// against FlushableMediaTaskQueues, which should go away.
virtual bool IsDispatchReliable() { return true; }
// Convenience method for getting an AbstractThread for the main thread.
static AbstractThread* MainThread();

View File

@ -321,6 +321,7 @@ public:
aDispatcher.AssertIsTailDispatcherIfRequired();
MutexAutoLock lock(mMutex);
MOZ_ASSERT(aResponseThread->IsDispatchReliable());
MOZ_DIAGNOSTIC_ASSERT(!IsExclusive || !mHaveConsumer);
mHaveConsumer = true;
nsRefPtr<ThenValueBase> thenValue = new ThenValue<ThisType, ResolveMethodType, RejectMethodType>(
@ -670,6 +671,7 @@ ProxyInternal(AbstractThread* aTarget, MethodCallBase<PromiseType>* aMethodCall,
{
nsRefPtr<typename PromiseType::Private> p = new (typename PromiseType::Private)(aCallerName);
nsRefPtr<ProxyRunnable<PromiseType>> r = new ProxyRunnable<PromiseType>(p, aMethodCall);
MOZ_ASSERT(aTarget->IsDispatchReliable());
aDispatcher.AddTask(aTarget, r.forget());
return Move(p);
}

View File

@ -56,14 +56,6 @@ MediaTaskQueue::TailDispatcher()
return *mTailDispatcher;
}
nsresult
MediaTaskQueue::ForceDispatch(TemporaryRef<nsIRunnable> aRunnable)
{
AssertInTailDispatchIfNeeded(); // Do this before acquiring the monitor.
MonitorAutoLock mon(mQueueMonitor);
return DispatchLocked(aRunnable, Forced);
}
nsresult
MediaTaskQueue::DispatchLocked(TemporaryRef<nsIRunnable> aRunnable,
DispatchMode aMode)
@ -75,7 +67,7 @@ MediaTaskQueue::DispatchLocked(TemporaryRef<nsIRunnable> aRunnable,
if (mIsShutdown) {
return NS_ERROR_FAILURE;
}
mTasks.push(TaskQueueEntry(aRunnable, aMode == Forced));
mTasks.push(aRunnable);
if (mIsRunning) {
return NS_OK;
}
@ -199,13 +191,9 @@ FlushableMediaTaskQueue::FlushLocked()
mQueueMonitor.AssertCurrentThreadOwns();
MOZ_ASSERT(mIsFlushing);
// Clear the tasks, but preserve those with mForceDispatch by re-appending
// them to the queue.
size_t numTasks = mTasks.size();
for (size_t i = 0; i < numTasks; ++i) {
if (mTasks.front().mForceDispatch) {
mTasks.push(mTasks.front());
}
// Clear the tasks. If this strikes you as awful, stop using a
// FlushableMediaTaskQueue.
while (!mTasks.empty()) {
mTasks.pop();
}
}
@ -238,7 +226,7 @@ MediaTaskQueue::Runner::Run()
mon.NotifyAll();
return NS_OK;
}
event = mQueue->mTasks.front().mRunnable;
event = mQueue->mTasks.front();
mQueue->mTasks.pop();
}
MOZ_ASSERT(event);

View File

@ -80,15 +80,11 @@ public:
{
RefPtr<nsIRunnable> r(aRunnable);
MonitorAutoLock mon(mQueueMonitor);
nsresult rv = DispatchLocked(r, Forced);
nsresult rv = DispatchLocked(r, AbortIfFlushing);
MOZ_DIAGNOSTIC_ASSERT(aFailureHandling == DontAssertDispatchSuccess || NS_SUCCEEDED(rv));
unused << rv;
}
// This should only be used for things that absolutely can't afford to be
// flushed. Normal operations should use Dispatch.
nsresult ForceDispatch(TemporaryRef<nsIRunnable> aRunnable);
// DEPRECATED! Do not us, if a flush happens at the same time, this function
// can hang and block forever!
nsresult SyncDispatch(TemporaryRef<nsIRunnable> aRunnable);
@ -123,7 +119,7 @@ protected:
// mQueueMonitor must be held.
void AwaitIdleLocked();
enum DispatchMode { AbortIfFlushing, IgnoreFlushing, Forced };
enum DispatchMode { AbortIfFlushing, IgnoreFlushing };
nsresult DispatchLocked(TemporaryRef<nsIRunnable> aRunnable,
DispatchMode aMode);
@ -133,17 +129,8 @@ protected:
// Monitor that protects the queue and mIsRunning;
Monitor mQueueMonitor;
struct TaskQueueEntry {
RefPtr<nsIRunnable> mRunnable;
bool mForceDispatch;
explicit TaskQueueEntry(TemporaryRef<nsIRunnable> aRunnable,
bool aForceDispatch = false)
: mRunnable(aRunnable), mForceDispatch(aForceDispatch) {}
};
// Queue of tasks to run.
std::queue<TaskQueueEntry> mTasks;
std::queue<RefPtr<nsIRunnable>> mTasks;
// The thread currently running the task queue. We store a reference
// to this so that IsCurrentThreadIn() can tell if the current thread
@ -222,6 +209,8 @@ public:
nsresult FlushAndDispatch(TemporaryRef<nsIRunnable> aRunnable);
void Flush();
bool IsDispatchReliable() override { return false; }
private:
class MOZ_STACK_CLASS AutoSetFlushing