mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 14:30:27 +00:00
3d36fa43e7
- Bug 1173641 - Hoist shutdown promise resolution into a helper. r=jww (1a02bd90a) - Bug 1173641 - Null out the thread pool when resolving shutdown. r=jww (ab3f723d5) - Bug 1173641 - Remove now-unnecessary null-out in MediaDecoderReader::BreakCycles. r=jww (3330778c6) - Bug 1173656 - Disallow TrackID reuse in TrackUnionStream. r=roc (7f4da1ea2) - Bug 1175768 - Implement SilentReadAt. r=jya (ece3c2ffa) - Bug 1178437 - Assert OnTaskQueue for most of the remaining MDSM methods. r=jww (da13ec549) - Bug 1178437 - Remove ReadOnWrongThread. r=jww (f9cf8946d) - Bug 1178437 - Dispatch SetFragmentEndTime. r=jww (740ce9882) - Bug 1178437 - Make mRealTime const and allow it to be accessed on any thread. r=jww (a65c22f1f) - Bug 1139964 part 1. Factor out the guts of BackstagePass::Resolve and BackstagePass::Enumerate to allow reuse for other globals that want to opt in to Exposed=System WebIDL annotations. r=smaug (d5eb8c704) - Bug 1139964 part 2. Add classinfo helpers for the various message manager stuff to install WebIDL Exposed=System things on those globals. r=smaug (47085f2a6) - Bug 1139964 part 3. Add a test. r=bzbarsky (d87e0907b) - Bug 1130028 - Custom elements, set registered prototype in compartment of caller of registerElement. r=mrbkap (5bd643614) - Bug 1130028 - Send inputmethod-contextchange to systemapp to hide keyboard when frame crash. r=yxl (1e100121f) - Bug 1156629 - OpenGL core context deprecated default VAO. r=jgilbert (5ecabb650) - Bug 1110120 - Remove use of UniquePtr for XFB and UB tracking.; r=smaug (92ebc132a) - Bug 1167504 - Part 11: Clean up buffer binding constraints. r=jgilbert (4f3005203) - Bug 1167504 - Part 13: Unbind buffers from cached state on buffer deletion. r=jgilbert (bb9e3f53d) - Bug 1180523 - Part 1: Store the audio mute/volume information on the outer window; r=baku (3b686c6b9) - line endings dos->unix (d7491a87c) - Bug 1153258 - directly instantiate nsStandardURL in nsChromeProtocolHandler.cpp; r=bsmedberg (01150c663) - Bug 1175344 - Include nsContentUtils.h explicitly to avoid compile error on unified building. r=ehsan (10a3d42ac) - Bug 959752 - Make the network predictor work under e10s. r=mcmanus (3b46a6b65) - Bug 1159747 - delete h2 static compression table in such a way to avoid crashes after network changes. r=mcmanus (ed34f8d80) - Bug 1173016 - Cache the basic waveform PeriodicWaves. r=karlt (d64c962f0) - part of Bug 1165816 - Cancel remote application reputation requests after a certain timeout. r=gcp (4cdc98d99) - Bug 1082837 - Call content policies on cached image redirects in imgLoader::ValidateSecurityInfo. Content policies check the last hop (final uri) of the cached image. For Mixed Content Blocker, we do an additional check to see if any of the intermediary hops went through an insecure redirect. r=smaug, feedback=seth (ffaf3debe) - Bug 1082837 - Use nsresult for static ShouldLoad and use NS_IMETHODIMP for nsIContentPolicy::ShouldLoad(). CLOSED TREE (acde35e25)
295 lines
8.0 KiB
C++
295 lines
8.0 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
/* 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/. */
|
|
|
|
#include "MediaTaskQueue.h"
|
|
#include "nsThreadUtils.h"
|
|
#include "SharedThreadPool.h"
|
|
|
|
namespace mozilla {
|
|
|
|
MediaTaskQueue::MediaTaskQueue(already_AddRefed<SharedThreadPool> aPool,
|
|
bool aRequireTailDispatch)
|
|
: AbstractThread(aRequireTailDispatch)
|
|
, mPool(aPool)
|
|
, mQueueMonitor("MediaTaskQueue::Queue")
|
|
, mTailDispatcher(nullptr)
|
|
, mIsRunning(false)
|
|
, mIsShutdown(false)
|
|
, mIsFlushing(false)
|
|
{
|
|
MOZ_COUNT_CTOR(MediaTaskQueue);
|
|
}
|
|
|
|
MediaTaskQueue::~MediaTaskQueue()
|
|
{
|
|
MonitorAutoLock mon(mQueueMonitor);
|
|
MOZ_ASSERT(mIsShutdown);
|
|
MOZ_COUNT_DTOR(MediaTaskQueue);
|
|
}
|
|
|
|
TaskDispatcher&
|
|
MediaTaskQueue::TailDispatcher()
|
|
{
|
|
MOZ_ASSERT(IsCurrentThreadIn());
|
|
MOZ_ASSERT(mTailDispatcher);
|
|
return *mTailDispatcher;
|
|
}
|
|
|
|
nsresult
|
|
MediaTaskQueue::DispatchLocked(already_AddRefed<nsIRunnable> aRunnable,
|
|
DispatchMode aMode, DispatchFailureHandling aFailureHandling,
|
|
DispatchReason aReason)
|
|
{
|
|
nsCOMPtr<nsIRunnable> r = aRunnable;
|
|
AbstractThread* currentThread;
|
|
if (aReason != TailDispatch && (currentThread = GetCurrent()) && currentThread->RequiresTailDispatch()) {
|
|
currentThread->TailDispatcher().AddTask(this, r.forget(), aFailureHandling);
|
|
return NS_OK;
|
|
}
|
|
|
|
mQueueMonitor.AssertCurrentThreadOwns();
|
|
if (mIsFlushing && aMode == AbortIfFlushing) {
|
|
return NS_ERROR_ABORT;
|
|
}
|
|
if (mIsShutdown) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
mTasks.push(r.forget());
|
|
if (mIsRunning) {
|
|
return NS_OK;
|
|
}
|
|
RefPtr<nsIRunnable> runner(new Runner(this));
|
|
nsresult rv = mPool->Dispatch(runner, NS_DISPATCH_NORMAL);
|
|
if (NS_FAILED(rv)) {
|
|
NS_WARNING("Failed to dispatch runnable to run MediaTaskQueue");
|
|
return rv;
|
|
}
|
|
mIsRunning = true;
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
class MediaTaskQueueSyncRunnable : public nsRunnable {
|
|
public:
|
|
explicit MediaTaskQueueSyncRunnable(already_AddRefed<nsIRunnable> aRunnable)
|
|
: mRunnable(aRunnable)
|
|
, mMonitor("MediaTaskQueueSyncRunnable")
|
|
, mDone(false)
|
|
{
|
|
}
|
|
|
|
NS_IMETHOD Run() {
|
|
nsresult rv = mRunnable->Run();
|
|
{
|
|
MonitorAutoLock mon(mMonitor);
|
|
mDone = true;
|
|
mon.NotifyAll();
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
void WaitUntilDone() {
|
|
MonitorAutoLock mon(mMonitor);
|
|
while (!mDone) {
|
|
mon.Wait();
|
|
}
|
|
}
|
|
private:
|
|
RefPtr<nsIRunnable> mRunnable;
|
|
Monitor mMonitor;
|
|
bool mDone;
|
|
};
|
|
|
|
void
|
|
MediaTaskQueue::SyncDispatch(already_AddRefed<nsIRunnable> aRunnable) {
|
|
NS_WARNING("MediaTaskQueue::SyncDispatch is deprecated and potentially dangerous. Don't use!");
|
|
nsRefPtr<MediaTaskQueueSyncRunnable> task(new MediaTaskQueueSyncRunnable(Move(aRunnable)));
|
|
|
|
// Tail dispatchers don't interact nicely with sync dispatch. We require that
|
|
// nothing is already in the tail dispatcher, and then sidestep it for this
|
|
// task.
|
|
MOZ_ASSERT_IF(AbstractThread::GetCurrent(),
|
|
!AbstractThread::GetCurrent()->TailDispatcher().HasTasksFor(this));
|
|
nsRefPtr<MediaTaskQueueSyncRunnable> taskRef = task;
|
|
Dispatch(taskRef.forget(), AssertDispatchSuccess, TailDispatch);
|
|
|
|
task->WaitUntilDone();
|
|
}
|
|
|
|
void
|
|
MediaTaskQueue::AwaitIdle()
|
|
{
|
|
MonitorAutoLock mon(mQueueMonitor);
|
|
AwaitIdleLocked();
|
|
}
|
|
|
|
void
|
|
MediaTaskQueue::AwaitIdleLocked()
|
|
{
|
|
// Make sure there are no tasks for this queue waiting in the caller's tail
|
|
// dispatcher.
|
|
MOZ_ASSERT_IF(AbstractThread::GetCurrent(),
|
|
!AbstractThread::GetCurrent()->TailDispatcher().HasTasksFor(this));
|
|
|
|
mQueueMonitor.AssertCurrentThreadOwns();
|
|
MOZ_ASSERT(mIsRunning || mTasks.empty());
|
|
while (mIsRunning) {
|
|
mQueueMonitor.Wait();
|
|
}
|
|
}
|
|
|
|
void
|
|
MediaTaskQueue::AwaitShutdownAndIdle()
|
|
{
|
|
// Make sure there are no tasks for this queue waiting in the caller's tail
|
|
// dispatcher.
|
|
MOZ_ASSERT_IF(AbstractThread::GetCurrent(),
|
|
!AbstractThread::GetCurrent()->TailDispatcher().HasTasksFor(this));
|
|
|
|
MonitorAutoLock mon(mQueueMonitor);
|
|
while (!mIsShutdown) {
|
|
mQueueMonitor.Wait();
|
|
}
|
|
AwaitIdleLocked();
|
|
}
|
|
|
|
nsRefPtr<ShutdownPromise>
|
|
MediaTaskQueue::BeginShutdown()
|
|
{
|
|
// Dispatch any tasks for this queue waiting in the caller's tail dispatcher,
|
|
// since this is the last opportunity to do so.
|
|
if (AbstractThread* currentThread = AbstractThread::GetCurrent()) {
|
|
currentThread->TailDispatcher().DispatchTasksFor(this);
|
|
}
|
|
|
|
MonitorAutoLock mon(mQueueMonitor);
|
|
mIsShutdown = true;
|
|
nsRefPtr<ShutdownPromise> p = mShutdownPromise.Ensure(__func__);
|
|
MaybeResolveShutdown();
|
|
mon.NotifyAll();
|
|
return p;
|
|
}
|
|
|
|
void
|
|
FlushableMediaTaskQueue::Flush()
|
|
{
|
|
MonitorAutoLock mon(mQueueMonitor);
|
|
AutoSetFlushing autoFlush(this);
|
|
FlushLocked();
|
|
AwaitIdleLocked();
|
|
}
|
|
|
|
nsresult
|
|
FlushableMediaTaskQueue::FlushAndDispatch(already_AddRefed<nsIRunnable> aRunnable)
|
|
{
|
|
MonitorAutoLock mon(mQueueMonitor);
|
|
AutoSetFlushing autoFlush(this);
|
|
FlushLocked();
|
|
nsCOMPtr<nsIRunnable> r = dont_AddRef(aRunnable.take());
|
|
nsresult rv = DispatchLocked(r.forget(), IgnoreFlushing, AssertDispatchSuccess);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
AwaitIdleLocked();
|
|
return NS_OK;
|
|
}
|
|
|
|
void
|
|
FlushableMediaTaskQueue::FlushLocked()
|
|
{
|
|
// Make sure there are no tasks for this queue waiting in the caller's tail
|
|
// dispatcher.
|
|
MOZ_ASSERT_IF(AbstractThread::GetCurrent(),
|
|
!AbstractThread::GetCurrent()->TailDispatcher().HasTasksFor(this));
|
|
|
|
mQueueMonitor.AssertCurrentThreadOwns();
|
|
MOZ_ASSERT(mIsFlushing);
|
|
|
|
// Clear the tasks.
|
|
while (!mTasks.empty()) {
|
|
mTasks.pop();
|
|
}
|
|
}
|
|
|
|
bool
|
|
MediaTaskQueue::IsEmpty()
|
|
{
|
|
MonitorAutoLock mon(mQueueMonitor);
|
|
return mTasks.empty();
|
|
}
|
|
|
|
bool
|
|
MediaTaskQueue::IsCurrentThreadIn()
|
|
{
|
|
bool in = NS_GetCurrentThread() == mRunningThread;
|
|
MOZ_ASSERT(in == (GetCurrent() == this));
|
|
return in;
|
|
}
|
|
|
|
nsresult
|
|
MediaTaskQueue::Runner::Run()
|
|
{
|
|
RefPtr<nsIRunnable> event;
|
|
{
|
|
MonitorAutoLock mon(mQueue->mQueueMonitor);
|
|
MOZ_ASSERT(mQueue->mIsRunning);
|
|
if (mQueue->mTasks.size() == 0) {
|
|
mQueue->mIsRunning = false;
|
|
mQueue->MaybeResolveShutdown();
|
|
mon.NotifyAll();
|
|
return NS_OK;
|
|
}
|
|
event = mQueue->mTasks.front();
|
|
mQueue->mTasks.pop();
|
|
}
|
|
MOZ_ASSERT(event);
|
|
|
|
// Note that dropping the queue monitor before running the task, and
|
|
// taking the monitor again after the task has run ensures we have memory
|
|
// fences enforced. This means that if the object we're calling wasn't
|
|
// designed to be threadsafe, it will be, provided we're only calling it
|
|
// in this task queue.
|
|
{
|
|
AutoTaskGuard g(mQueue);
|
|
event->Run();
|
|
}
|
|
|
|
// Drop the reference to event. The event will hold a reference to the
|
|
// object it's calling, and we don't want to keep it alive, it may be
|
|
// making assumptions what holds references to it. This is especially
|
|
// the case if the object is waiting for us to shutdown, so that it
|
|
// can shutdown (like in the MediaDecoderStateMachine's SHUTDOWN case).
|
|
event = nullptr;
|
|
|
|
{
|
|
MonitorAutoLock mon(mQueue->mQueueMonitor);
|
|
if (mQueue->mTasks.size() == 0) {
|
|
// No more events to run. Exit the task runner.
|
|
mQueue->mIsRunning = false;
|
|
mQueue->MaybeResolveShutdown();
|
|
mon.NotifyAll();
|
|
return NS_OK;
|
|
}
|
|
}
|
|
|
|
// There's at least one more event that we can run. Dispatch this Runner
|
|
// to the thread pool again to ensure it runs again. Note that we don't just
|
|
// run in a loop here so that we don't hog the thread pool. This means we may
|
|
// run on another thread next time, but we rely on the memory fences from
|
|
// mQueueMonitor for thread safety of non-threadsafe tasks.
|
|
nsresult rv = mQueue->mPool->Dispatch(this, NS_DISPATCH_NORMAL);
|
|
if (NS_FAILED(rv)) {
|
|
// Failed to dispatch, shutdown!
|
|
MonitorAutoLock mon(mQueue->mQueueMonitor);
|
|
mQueue->mIsRunning = false;
|
|
mQueue->mIsShutdown = true;
|
|
mQueue->MaybeResolveShutdown();
|
|
mon.NotifyAll();
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
} // namespace mozilla
|