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, void MaybeTailDispatch(already_AddRefed<nsIRunnable> aRunnable,
DispatchFailureHandling aFailureHandling = AssertDispatchSuccess); 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. // Convenience method for getting an AbstractThread for the main thread.
static AbstractThread* MainThread(); static AbstractThread* MainThread();

View File

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

View File

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

View File

@ -80,15 +80,11 @@ public:
{ {
RefPtr<nsIRunnable> r(aRunnable); RefPtr<nsIRunnable> r(aRunnable);
MonitorAutoLock mon(mQueueMonitor); MonitorAutoLock mon(mQueueMonitor);
nsresult rv = DispatchLocked(r, Forced); nsresult rv = DispatchLocked(r, AbortIfFlushing);
MOZ_DIAGNOSTIC_ASSERT(aFailureHandling == DontAssertDispatchSuccess || NS_SUCCEEDED(rv)); MOZ_DIAGNOSTIC_ASSERT(aFailureHandling == DontAssertDispatchSuccess || NS_SUCCEEDED(rv));
unused << 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 // DEPRECATED! Do not us, if a flush happens at the same time, this function
// can hang and block forever! // can hang and block forever!
nsresult SyncDispatch(TemporaryRef<nsIRunnable> aRunnable); nsresult SyncDispatch(TemporaryRef<nsIRunnable> aRunnable);
@ -123,7 +119,7 @@ protected:
// mQueueMonitor must be held. // mQueueMonitor must be held.
void AwaitIdleLocked(); void AwaitIdleLocked();
enum DispatchMode { AbortIfFlushing, IgnoreFlushing, Forced }; enum DispatchMode { AbortIfFlushing, IgnoreFlushing };
nsresult DispatchLocked(TemporaryRef<nsIRunnable> aRunnable, nsresult DispatchLocked(TemporaryRef<nsIRunnable> aRunnable,
DispatchMode aMode); DispatchMode aMode);
@ -133,17 +129,8 @@ protected:
// Monitor that protects the queue and mIsRunning; // Monitor that protects the queue and mIsRunning;
Monitor mQueueMonitor; 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. // 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 // The thread currently running the task queue. We store a reference
// to this so that IsCurrentThreadIn() can tell if the current thread // to this so that IsCurrentThreadIn() can tell if the current thread
@ -222,6 +209,8 @@ public:
nsresult FlushAndDispatch(TemporaryRef<nsIRunnable> aRunnable); nsresult FlushAndDispatch(TemporaryRef<nsIRunnable> aRunnable);
void Flush(); void Flush();
bool IsDispatchReliable() override { return false; }
private: private:
class MOZ_STACK_CLASS AutoSetFlushing class MOZ_STACK_CLASS AutoSetFlushing