зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1559919 - Finish the WorkerHolder cleanup - part 11 - WorkerHolder replaced by WorkerRef, r=asuth
Differential Revision: https://phabricator.services.mozilla.com/D35230 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
46c41f3318
Коммит
2a3e21430e
|
@ -1,71 +0,0 @@
|
||||||
/* -*- 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 "WorkerHolder.h"
|
|
||||||
#include "WorkerPrivate.h"
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
namespace dom {
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
void AssertOnOwningThread(void* aThread) {
|
|
||||||
if (MOZ_UNLIKELY(aThread != GetCurrentVirtualThread())) {
|
|
||||||
MOZ_CRASH_UNSAFE("WorkerHolder on the wrong thread.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
WorkerHolder::WorkerHolder(const char* aName, Behavior aBehavior)
|
|
||||||
: mWorkerPrivate(nullptr),
|
|
||||||
mBehavior(aBehavior),
|
|
||||||
mThread(GetCurrentVirtualThread()),
|
|
||||||
mName(aName) {}
|
|
||||||
|
|
||||||
WorkerHolder::~WorkerHolder() {
|
|
||||||
AssertOnOwningThread(mThread);
|
|
||||||
ReleaseWorkerInternal();
|
|
||||||
MOZ_ASSERT(mWorkerPrivate == nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WorkerHolder::HoldWorker(WorkerPrivate* aWorkerPrivate,
|
|
||||||
WorkerStatus aFailStatus) {
|
|
||||||
AssertOnOwningThread(mThread);
|
|
||||||
MOZ_ASSERT(aWorkerPrivate);
|
|
||||||
MOZ_ASSERT(aFailStatus >= Canceling);
|
|
||||||
|
|
||||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
|
||||||
|
|
||||||
if (!aWorkerPrivate->AddHolder(this, aFailStatus)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
mWorkerPrivate = aWorkerPrivate;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WorkerHolder::ReleaseWorker() {
|
|
||||||
AssertOnOwningThread(mThread);
|
|
||||||
MOZ_ASSERT(mWorkerPrivate);
|
|
||||||
|
|
||||||
ReleaseWorkerInternal();
|
|
||||||
}
|
|
||||||
|
|
||||||
WorkerHolder::Behavior WorkerHolder::GetBehavior() const { return mBehavior; }
|
|
||||||
|
|
||||||
void WorkerHolder::ReleaseWorkerInternal() {
|
|
||||||
AssertOnOwningThread(mThread);
|
|
||||||
|
|
||||||
if (mWorkerPrivate) {
|
|
||||||
mWorkerPrivate->AssertIsOnWorkerThread();
|
|
||||||
mWorkerPrivate->RemoveHolder(this);
|
|
||||||
mWorkerPrivate = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace dom
|
|
||||||
} // namespace mozilla
|
|
|
@ -2047,7 +2047,7 @@ bool WorkerPrivate::PrincipalIsValid() const {
|
||||||
|
|
||||||
WorkerPrivate::WorkerThreadAccessible::WorkerThreadAccessible(
|
WorkerPrivate::WorkerThreadAccessible::WorkerThreadAccessible(
|
||||||
WorkerPrivate* const aParent)
|
WorkerPrivate* const aParent)
|
||||||
: mNumHoldersPreventingShutdownStart(0),
|
: mNumWorkerRefsPreventingShutdownStart(0),
|
||||||
mDebuggerEventLoopLevel(0),
|
mDebuggerEventLoopLevel(0),
|
||||||
mErrorHandlerRecursionCount(0),
|
mErrorHandlerRecursionCount(0),
|
||||||
mNextTimeoutId(1),
|
mNextTimeoutId(1),
|
||||||
|
@ -2706,7 +2706,7 @@ void WorkerPrivate::DoRunLoop(JSContext* aCx) {
|
||||||
while (mControlQueue.IsEmpty() &&
|
while (mControlQueue.IsEmpty() &&
|
||||||
!(debuggerRunnablesPending = !mDebuggerQueue.IsEmpty()) &&
|
!(debuggerRunnablesPending = !mDebuggerQueue.IsEmpty()) &&
|
||||||
!(normalRunnablesPending = NS_HasPendingEvents(mThread)) &&
|
!(normalRunnablesPending = NS_HasPendingEvents(mThread)) &&
|
||||||
!(mStatus != Running && !HasActiveHolders())) {
|
!(mStatus != Running && !HasActiveWorkerRefs())) {
|
||||||
WaitForWorkerEvents();
|
WaitForWorkerEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2724,7 +2724,7 @@ void WorkerPrivate::DoRunLoop(JSContext* aCx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// if all holders are done then we can kill this thread.
|
// if all holders are done then we can kill this thread.
|
||||||
if (currentStatus != Running && !HasActiveHolders()) {
|
if (currentStatus != Running && !HasActiveWorkerRefs()) {
|
||||||
// Now we are ready to kill the worker thread.
|
// Now we are ready to kill the worker thread.
|
||||||
if (currentStatus == Canceling) {
|
if (currentStatus == Canceling) {
|
||||||
NotifyInternal(Killing);
|
NotifyInternal(Killing);
|
||||||
|
@ -3503,7 +3503,9 @@ void WorkerPrivate::RemoveChildWorker(WorkerPrivate* aChildWorker) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WorkerPrivate::AddHolder(WorkerHolder* aHolder, WorkerStatus aFailStatus) {
|
bool WorkerPrivate::AddWorkerRef(WorkerRef* aWorkerRef,
|
||||||
|
WorkerStatus aFailStatus) {
|
||||||
|
MOZ_ASSERT(aWorkerRef);
|
||||||
MOZ_ACCESS_THREAD_BOUND(mWorkerThreadAccessible, data);
|
MOZ_ACCESS_THREAD_BOUND(mWorkerThreadAccessible, data);
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -3514,46 +3516,46 @@ bool WorkerPrivate::AddHolder(WorkerHolder* aHolder, WorkerStatus aFailStatus) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_ASSERT(!data->mHolders.Contains(aHolder), "Already know about this one!");
|
MOZ_ASSERT(!data->mWorkerRefs.Contains(aWorkerRef),
|
||||||
|
"Already know about this one!");
|
||||||
|
|
||||||
if (aHolder->GetBehavior() == WorkerHolder::PreventIdleShutdownStart) {
|
if (aWorkerRef->IsPreventingShutdown()) {
|
||||||
if (!data->mNumHoldersPreventingShutdownStart &&
|
if (!data->mNumWorkerRefsPreventingShutdownStart &&
|
||||||
!ModifyBusyCountFromWorker(true)) {
|
!ModifyBusyCountFromWorker(true)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
data->mNumHoldersPreventingShutdownStart += 1;
|
data->mNumWorkerRefsPreventingShutdownStart += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
data->mHolders.AppendElement(aHolder);
|
data->mWorkerRefs.AppendElement(aWorkerRef);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorkerPrivate::RemoveHolder(WorkerHolder* aHolder) {
|
void WorkerPrivate::RemoveWorkerRef(WorkerRef* aWorkerRef) {
|
||||||
|
MOZ_ASSERT(aWorkerRef);
|
||||||
MOZ_ACCESS_THREAD_BOUND(mWorkerThreadAccessible, data);
|
MOZ_ACCESS_THREAD_BOUND(mWorkerThreadAccessible, data);
|
||||||
|
|
||||||
MOZ_ASSERT(data->mHolders.Contains(aHolder), "Didn't know about this one!");
|
MOZ_ASSERT(data->mWorkerRefs.Contains(aWorkerRef),
|
||||||
data->mHolders.RemoveElement(aHolder);
|
"Didn't know about this one!");
|
||||||
|
data->mWorkerRefs.RemoveElement(aWorkerRef);
|
||||||
|
|
||||||
if (aHolder->GetBehavior() == WorkerHolder::PreventIdleShutdownStart) {
|
if (aWorkerRef->IsPreventingShutdown()) {
|
||||||
data->mNumHoldersPreventingShutdownStart -= 1;
|
data->mNumWorkerRefsPreventingShutdownStart -= 1;
|
||||||
if (!data->mNumHoldersPreventingShutdownStart &&
|
if (!data->mNumWorkerRefsPreventingShutdownStart &&
|
||||||
!ModifyBusyCountFromWorker(false)) {
|
!ModifyBusyCountFromWorker(false)) {
|
||||||
NS_WARNING("Failed to modify busy count!");
|
NS_WARNING("Failed to modify busy count!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorkerPrivate::NotifyHolders(WorkerStatus aStatus) {
|
void WorkerPrivate::NotifyWorkerRefs(WorkerStatus aStatus) {
|
||||||
MOZ_ACCESS_THREAD_BOUND(mWorkerThreadAccessible, data);
|
MOZ_ACCESS_THREAD_BOUND(mWorkerThreadAccessible, data);
|
||||||
|
|
||||||
NS_ASSERTION(aStatus > Closing, "Bad status!");
|
NS_ASSERTION(aStatus > Closing, "Bad status!");
|
||||||
|
|
||||||
nsTObserverArray<WorkerHolder*>::ForwardIterator iter(data->mHolders);
|
nsTObserverArray<WorkerRef*>::ForwardIterator iter(data->mWorkerRefs);
|
||||||
while (iter.HasMore()) {
|
while (iter.HasMore()) {
|
||||||
WorkerHolder* holder = iter.GetNext();
|
iter.GetNext()->Notify();
|
||||||
if (!holder->Notify(aStatus)) {
|
|
||||||
NS_WARNING("Failed to notify holder!");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AutoTArray<WorkerPrivate*, 10> children;
|
AutoTArray<WorkerPrivate*, 10> children;
|
||||||
|
@ -4060,7 +4062,7 @@ bool WorkerPrivate::NotifyInternal(WorkerStatus aStatus) {
|
||||||
|
|
||||||
// Let all our holders know the new status.
|
// Let all our holders know the new status.
|
||||||
if (aStatus > Closing) {
|
if (aStatus > Closing) {
|
||||||
NotifyHolders(aStatus);
|
NotifyWorkerRefs(aStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this is the first time our status has changed then we need to clear the
|
// If this is the first time our status has changed then we need to clear the
|
||||||
|
@ -4801,11 +4803,13 @@ void WorkerPrivate::AssertIsOnWorkerThread() const {
|
||||||
void WorkerPrivate::DumpCrashInformation(nsACString& aString) {
|
void WorkerPrivate::DumpCrashInformation(nsACString& aString) {
|
||||||
MOZ_ACCESS_THREAD_BOUND(mWorkerThreadAccessible, data);
|
MOZ_ACCESS_THREAD_BOUND(mWorkerThreadAccessible, data);
|
||||||
|
|
||||||
nsTObserverArray<WorkerHolder*>::ForwardIterator iter(data->mHolders);
|
nsTObserverArray<WorkerRef*>::ForwardIterator iter(data->mWorkerRefs);
|
||||||
while (iter.HasMore()) {
|
while (iter.HasMore()) {
|
||||||
WorkerHolder* holder = iter.GetNext();
|
WorkerRef* workerRef = iter.GetNext();
|
||||||
|
if (workerRef->IsPreventingShutdown()) {
|
||||||
aString.Append("|");
|
aString.Append("|");
|
||||||
aString.Append(holder->Name());
|
aString.Append(workerRef->Name());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#define mozilla_dom_workers_workerprivate_h__
|
#define mozilla_dom_workers_workerprivate_h__
|
||||||
|
|
||||||
#include "mozilla/dom/WorkerCommon.h"
|
#include "mozilla/dom/WorkerCommon.h"
|
||||||
|
#include "mozilla/dom/WorkerStatus.h"
|
||||||
#include "mozilla/Attributes.h"
|
#include "mozilla/Attributes.h"
|
||||||
#include "mozilla/CondVar.h"
|
#include "mozilla/CondVar.h"
|
||||||
#include "mozilla/DOMEventTargetHelper.h"
|
#include "mozilla/DOMEventTargetHelper.h"
|
||||||
|
@ -20,7 +21,6 @@
|
||||||
|
|
||||||
#include "js/ContextOptions.h"
|
#include "js/ContextOptions.h"
|
||||||
#include "mozilla/dom/Worker.h"
|
#include "mozilla/dom/Worker.h"
|
||||||
#include "mozilla/dom/WorkerHolder.h"
|
|
||||||
#include "mozilla/dom/WorkerLoadInfo.h"
|
#include "mozilla/dom/WorkerLoadInfo.h"
|
||||||
#include "mozilla/dom/workerinternals/JSSettings.h"
|
#include "mozilla/dom/workerinternals/JSSettings.h"
|
||||||
#include "mozilla/dom/workerinternals/Queue.h"
|
#include "mozilla/dom/workerinternals/Queue.h"
|
||||||
|
@ -52,6 +52,7 @@ class WorkerDebuggerGlobalScope;
|
||||||
class WorkerErrorReport;
|
class WorkerErrorReport;
|
||||||
class WorkerEventTarget;
|
class WorkerEventTarget;
|
||||||
class WorkerGlobalScope;
|
class WorkerGlobalScope;
|
||||||
|
class WorkerRef;
|
||||||
class WorkerRunnable;
|
class WorkerRunnable;
|
||||||
class WorkerDebuggeeRunnable;
|
class WorkerDebuggeeRunnable;
|
||||||
class WorkerThread;
|
class WorkerThread;
|
||||||
|
@ -922,7 +923,7 @@ class WorkerPrivate : public RelativeTimeline {
|
||||||
void WaitForWorkerEvents();
|
void WaitForWorkerEvents();
|
||||||
|
|
||||||
// If the worker shutdown status is equal or greater then aFailStatus, this
|
// If the worker shutdown status is equal or greater then aFailStatus, this
|
||||||
// operation will fail and nullptr will be returned. See WorkerHolder.h for
|
// operation will fail and nullptr will be returned. See WorkerStatus.h for
|
||||||
// more information about the correct value to use.
|
// more information about the correct value to use.
|
||||||
already_AddRefed<nsIEventTarget> CreateNewSyncLoop(WorkerStatus aFailStatus);
|
already_AddRefed<nsIEventTarget> CreateNewSyncLoop(WorkerStatus aFailStatus);
|
||||||
|
|
||||||
|
@ -938,16 +939,18 @@ class WorkerPrivate : public RelativeTimeline {
|
||||||
|
|
||||||
void ShutdownGCTimers();
|
void ShutdownGCTimers();
|
||||||
|
|
||||||
bool AddHolder(WorkerHolder* aHolder, WorkerStatus aFailStatus);
|
friend class WorkerRef;
|
||||||
|
|
||||||
void RemoveHolder(WorkerHolder* aHolder);
|
bool AddWorkerRef(WorkerRef* aWorkerRefer, WorkerStatus aFailStatus);
|
||||||
|
|
||||||
void NotifyHolders(WorkerStatus aStatus);
|
void RemoveWorkerRef(WorkerRef* aWorkerRef);
|
||||||
|
|
||||||
bool HasActiveHolders() {
|
void NotifyWorkerRefs(WorkerStatus aStatus);
|
||||||
|
|
||||||
|
bool HasActiveWorkerRefs() {
|
||||||
MOZ_ACCESS_THREAD_BOUND(mWorkerThreadAccessible, data);
|
MOZ_ACCESS_THREAD_BOUND(mWorkerThreadAccessible, data);
|
||||||
return !(data->mChildWorkers.IsEmpty() && data->mTimeouts.IsEmpty() &&
|
return !(data->mChildWorkers.IsEmpty() && data->mTimeouts.IsEmpty() &&
|
||||||
data->mHolders.IsEmpty());
|
data->mWorkerRefs.IsEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal logic to dispatch a runnable. This is separate from Dispatch()
|
// Internal logic to dispatch a runnable. This is separate from Dispatch()
|
||||||
|
@ -965,7 +968,6 @@ class WorkerPrivate : public RelativeTimeline {
|
||||||
|
|
||||||
class EventTarget;
|
class EventTarget;
|
||||||
friend class EventTarget;
|
friend class EventTarget;
|
||||||
friend class mozilla::dom::WorkerHolder;
|
|
||||||
friend class AutoSyncLoopHolder;
|
friend class AutoSyncLoopHolder;
|
||||||
|
|
||||||
struct TimeoutInfo;
|
struct TimeoutInfo;
|
||||||
|
@ -1084,7 +1086,7 @@ class WorkerPrivate : public RelativeTimeline {
|
||||||
RefPtr<WorkerGlobalScope> mScope;
|
RefPtr<WorkerGlobalScope> mScope;
|
||||||
RefPtr<WorkerDebuggerGlobalScope> mDebuggerScope;
|
RefPtr<WorkerDebuggerGlobalScope> mDebuggerScope;
|
||||||
nsTArray<WorkerPrivate*> mChildWorkers;
|
nsTArray<WorkerPrivate*> mChildWorkers;
|
||||||
nsTObserverArray<WorkerHolder*> mHolders;
|
nsTObserverArray<WorkerRef*> mWorkerRefs;
|
||||||
nsTArray<nsAutoPtr<TimeoutInfo>> mTimeouts;
|
nsTArray<nsAutoPtr<TimeoutInfo>> mTimeouts;
|
||||||
|
|
||||||
nsCOMPtr<nsITimer> mTimer;
|
nsCOMPtr<nsITimer> mTimer;
|
||||||
|
@ -1096,7 +1098,7 @@ class WorkerPrivate : public RelativeTimeline {
|
||||||
|
|
||||||
UniquePtr<ClientSource> mClientSource;
|
UniquePtr<ClientSource> mClientSource;
|
||||||
|
|
||||||
uint32_t mNumHoldersPreventingShutdownStart;
|
uint32_t mNumWorkerRefsPreventingShutdownStart;
|
||||||
uint32_t mDebuggerEventLoopLevel;
|
uint32_t mDebuggerEventLoopLevel;
|
||||||
|
|
||||||
uint32_t mErrorHandlerRecursionCount;
|
uint32_t mErrorHandlerRecursionCount;
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
#include "WorkerRef.h"
|
#include "WorkerRef.h"
|
||||||
|
|
||||||
#include "mozilla/Unused.h"
|
#include "mozilla/Unused.h"
|
||||||
#include "WorkerHolder.h"
|
|
||||||
#include "WorkerRunnable.h"
|
#include "WorkerRunnable.h"
|
||||||
#include "WorkerPrivate.h"
|
#include "WorkerPrivate.h"
|
||||||
|
|
||||||
|
@ -43,46 +42,50 @@ class ReleaseRefControlRunnable final : public WorkerControlRunnable {
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
// WorkerRef::Holder
|
|
||||||
|
|
||||||
class WorkerRef::Holder final : public mozilla::dom::WorkerHolder {
|
|
||||||
public:
|
|
||||||
Holder(const char* aName, WorkerRef* aWorkerRef, Behavior aBehavior)
|
|
||||||
: mozilla::dom::WorkerHolder(aName, aBehavior), mWorkerRef(aWorkerRef) {}
|
|
||||||
|
|
||||||
bool Notify(WorkerStatus aStatus) override {
|
|
||||||
MOZ_ASSERT(mWorkerRef);
|
|
||||||
|
|
||||||
if (aStatus < Canceling) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Let's keep this object alive for the whole Notify() execution.
|
|
||||||
RefPtr<WorkerRef> workerRef;
|
|
||||||
workerRef = mWorkerRef;
|
|
||||||
|
|
||||||
workerRef->Notify();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
WorkerRef* mWorkerRef;
|
|
||||||
};
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// WorkerRef
|
// WorkerRef
|
||||||
|
|
||||||
WorkerRef::WorkerRef(WorkerPrivate* aWorkerPrivate)
|
WorkerRef::WorkerRef(WorkerPrivate* aWorkerPrivate, const char* aName,
|
||||||
: mWorkerPrivate(aWorkerPrivate) {
|
bool aIsPreventingShutdown)
|
||||||
|
: mWorkerPrivate(aWorkerPrivate),
|
||||||
|
mName(aName),
|
||||||
|
mIsPreventingShutdown(aIsPreventingShutdown),
|
||||||
|
mHolding(false) {
|
||||||
MOZ_ASSERT(aWorkerPrivate);
|
MOZ_ASSERT(aWorkerPrivate);
|
||||||
|
MOZ_ASSERT(aName);
|
||||||
|
|
||||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
WorkerRef::~WorkerRef() { NS_ASSERT_OWNINGTHREAD(WorkerRef); }
|
WorkerRef::~WorkerRef() {
|
||||||
|
NS_ASSERT_OWNINGTHREAD(WorkerRef);
|
||||||
|
ReleaseWorker();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorkerRef::ReleaseWorker() {
|
||||||
|
if (mHolding) {
|
||||||
|
MOZ_ASSERT(mWorkerPrivate);
|
||||||
|
|
||||||
|
mWorkerPrivate->RemoveWorkerRef(this);
|
||||||
|
mWorkerPrivate = nullptr;
|
||||||
|
|
||||||
|
mHolding = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WorkerRef::HoldWorker(WorkerStatus aStatus) {
|
||||||
|
MOZ_ASSERT(mWorkerPrivate);
|
||||||
|
MOZ_ASSERT(!mHolding);
|
||||||
|
|
||||||
|
if (NS_WARN_IF(!mWorkerPrivate->AddWorkerRef(this, aStatus))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
mHolding = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void WorkerRef::Notify() {
|
void WorkerRef::Notify() {
|
||||||
MOZ_ASSERT(mHolder);
|
|
||||||
NS_ASSERT_OWNINGTHREAD(WorkerRef);
|
NS_ASSERT_OWNINGTHREAD(WorkerRef);
|
||||||
|
|
||||||
if (!mCallback) {
|
if (!mCallback) {
|
||||||
|
@ -105,30 +108,30 @@ already_AddRefed<WeakWorkerRef> WeakWorkerRef::Create(
|
||||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||||
|
|
||||||
RefPtr<WeakWorkerRef> ref = new WeakWorkerRef(aWorkerPrivate);
|
RefPtr<WeakWorkerRef> ref = new WeakWorkerRef(aWorkerPrivate);
|
||||||
|
if (!ref->HoldWorker(Canceling)) {
|
||||||
// This holder doesn't keep the worker alive.
|
|
||||||
UniquePtr<Holder> holder(new Holder("WeakWorkerRef::Holder", ref,
|
|
||||||
WorkerHolder::AllowIdleShutdownStart));
|
|
||||||
if (NS_WARN_IF(!holder->HoldWorker(aWorkerPrivate, Canceling))) {
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ref->mHolder = std::move(holder);
|
|
||||||
ref->mCallback = std::move(aCallback);
|
ref->mCallback = std::move(aCallback);
|
||||||
|
|
||||||
return ref.forget();
|
return ref.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
WeakWorkerRef::WeakWorkerRef(WorkerPrivate* aWorkerPrivate)
|
WeakWorkerRef::WeakWorkerRef(WorkerPrivate* aWorkerPrivate)
|
||||||
: WorkerRef(aWorkerPrivate) {}
|
: WorkerRef(aWorkerPrivate, "WeakWorkerRef", false) {}
|
||||||
|
|
||||||
WeakWorkerRef::~WeakWorkerRef() = default;
|
WeakWorkerRef::~WeakWorkerRef() = default;
|
||||||
|
|
||||||
void WeakWorkerRef::Notify() {
|
void WeakWorkerRef::Notify() {
|
||||||
WorkerRef::Notify();
|
MOZ_ASSERT(mHolding);
|
||||||
|
MOZ_ASSERT(mWorkerPrivate);
|
||||||
|
|
||||||
mHolder = nullptr;
|
// Notify could drop the last reference to this object. We must keep it alive
|
||||||
mWorkerPrivate = nullptr;
|
// in order to call ReleaseWorker() immediately after.
|
||||||
|
RefPtr<WeakWorkerRef> kungFuGrip = this;
|
||||||
|
|
||||||
|
WorkerRef::Notify();
|
||||||
|
ReleaseWorker();
|
||||||
}
|
}
|
||||||
|
|
||||||
WorkerPrivate* WeakWorkerRef::GetPrivate() const {
|
WorkerPrivate* WeakWorkerRef::GetPrivate() const {
|
||||||
|
@ -168,27 +171,21 @@ already_AddRefed<StrongWorkerRef> StrongWorkerRef::CreateImpl(
|
||||||
MOZ_ASSERT(aWorkerPrivate);
|
MOZ_ASSERT(aWorkerPrivate);
|
||||||
MOZ_ASSERT(aName);
|
MOZ_ASSERT(aName);
|
||||||
|
|
||||||
RefPtr<StrongWorkerRef> ref = new StrongWorkerRef(aWorkerPrivate);
|
RefPtr<StrongWorkerRef> ref = new StrongWorkerRef(aWorkerPrivate, aName);
|
||||||
|
if (!ref->HoldWorker(aFailStatus)) {
|
||||||
// The worker is kept alive by this holder.
|
|
||||||
UniquePtr<Holder> holder(
|
|
||||||
new Holder(aName, ref, WorkerHolder::PreventIdleShutdownStart));
|
|
||||||
if (NS_WARN_IF(!holder->HoldWorker(aWorkerPrivate, aFailStatus))) {
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ref->mHolder = std::move(holder);
|
|
||||||
|
|
||||||
return ref.forget();
|
return ref.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
StrongWorkerRef::StrongWorkerRef(WorkerPrivate* aWorkerPrivate)
|
StrongWorkerRef::StrongWorkerRef(WorkerPrivate* aWorkerPrivate,
|
||||||
: WorkerRef(aWorkerPrivate) {}
|
const char* aName)
|
||||||
|
: WorkerRef(aWorkerPrivate, aName, true) {}
|
||||||
|
|
||||||
StrongWorkerRef::~StrongWorkerRef() { NS_ASSERT_OWNINGTHREAD(StrongWorkerRef); }
|
StrongWorkerRef::~StrongWorkerRef() = default;
|
||||||
|
|
||||||
WorkerPrivate* StrongWorkerRef::Private() const {
|
WorkerPrivate* StrongWorkerRef::Private() const {
|
||||||
MOZ_ASSERT(mHolder);
|
|
||||||
NS_ASSERT_OWNINGTHREAD(StrongWorkerRef);
|
NS_ASSERT_OWNINGTHREAD(StrongWorkerRef);
|
||||||
return mWorkerPrivate;
|
return mWorkerPrivate;
|
||||||
}
|
}
|
||||||
|
@ -226,28 +223,22 @@ already_AddRefed<IPCWorkerRef> IPCWorkerRef::Create(
|
||||||
MOZ_ASSERT(aWorkerPrivate);
|
MOZ_ASSERT(aWorkerPrivate);
|
||||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||||
|
|
||||||
RefPtr<IPCWorkerRef> ref = new IPCWorkerRef(aWorkerPrivate);
|
RefPtr<IPCWorkerRef> ref = new IPCWorkerRef(aWorkerPrivate, aName);
|
||||||
|
if (!ref->HoldWorker(Canceling)) {
|
||||||
// This holder doesn't keep the worker alive.
|
|
||||||
UniquePtr<Holder> holder(
|
|
||||||
new Holder(aName, ref, WorkerHolder::AllowIdleShutdownStart));
|
|
||||||
if (NS_WARN_IF(!holder->HoldWorker(aWorkerPrivate, Canceling))) {
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ref->mHolder = std::move(holder);
|
|
||||||
ref->mCallback = std::move(aCallback);
|
ref->mCallback = std::move(aCallback);
|
||||||
|
|
||||||
return ref.forget();
|
return ref.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCWorkerRef::IPCWorkerRef(WorkerPrivate* aWorkerPrivate)
|
IPCWorkerRef::IPCWorkerRef(WorkerPrivate* aWorkerPrivate, const char* aName)
|
||||||
: WorkerRef(aWorkerPrivate) {}
|
: WorkerRef(aWorkerPrivate, aName, false) {}
|
||||||
|
|
||||||
IPCWorkerRef::~IPCWorkerRef() = default;
|
IPCWorkerRef::~IPCWorkerRef() = default;
|
||||||
|
|
||||||
WorkerPrivate* IPCWorkerRef::Private() const {
|
WorkerPrivate* IPCWorkerRef::Private() const {
|
||||||
MOZ_ASSERT(mHolder);
|
|
||||||
NS_ASSERT_OWNINGTHREAD(IPCWorkerRef);
|
NS_ASSERT_OWNINGTHREAD(IPCWorkerRef);
|
||||||
return mWorkerPrivate;
|
return mWorkerPrivate;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
#define mozilla_dom_workers_WorkerRef_h
|
#define mozilla_dom_workers_WorkerRef_h
|
||||||
|
|
||||||
#include "mozilla/dom/WorkerCommon.h"
|
#include "mozilla/dom/WorkerCommon.h"
|
||||||
#include "mozilla/dom/WorkerHolder.h"
|
#include "mozilla/dom/WorkerStatus.h"
|
||||||
#include "mozilla/UniquePtr.h"
|
#include "mozilla/UniquePtr.h"
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ namespace dom {
|
||||||
* d. Firefox is shutting down.
|
* d. Firefox is shutting down.
|
||||||
*
|
*
|
||||||
* When a DOM Worker goes away, it does several steps. See more in
|
* When a DOM Worker goes away, it does several steps. See more in
|
||||||
* WorkerHolder.h. The DOM Worker thread will basically stop scheduling
|
* WorkerStatus.h. The DOM Worker thread will basically stop scheduling
|
||||||
* WorkerRunnables, and eventually WorkerControlRunnables. But if there is
|
* WorkerRunnables, and eventually WorkerControlRunnables. But if there is
|
||||||
* something preventing the shutting down, it will always possible to dispatch
|
* something preventing the shutting down, it will always possible to dispatch
|
||||||
* WorkerControlRunnables. Of course, at some point, the worker _must_ be
|
* WorkerControlRunnables. Of course, at some point, the worker _must_ be
|
||||||
|
@ -103,22 +103,33 @@ class StrongWorkerRef;
|
||||||
class ThreadSafeWorkerRef;
|
class ThreadSafeWorkerRef;
|
||||||
|
|
||||||
class WorkerRef {
|
class WorkerRef {
|
||||||
|
friend class WorkerPrivate;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NS_INLINE_DECL_REFCOUNTING(WorkerRef)
|
NS_INLINE_DECL_REFCOUNTING(WorkerRef)
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
class Holder;
|
WorkerRef(WorkerPrivate* aWorkerPrivate, const char* aName,
|
||||||
friend class Holder;
|
bool aIsPreventingShutdown);
|
||||||
|
|
||||||
explicit WorkerRef(WorkerPrivate* aWorkerPrivate);
|
|
||||||
virtual ~WorkerRef();
|
virtual ~WorkerRef();
|
||||||
|
|
||||||
virtual void Notify();
|
virtual void Notify();
|
||||||
|
|
||||||
|
bool HoldWorker(WorkerStatus aStatus);
|
||||||
|
void ReleaseWorker();
|
||||||
|
|
||||||
|
bool IsPreventingShutdown() const { return mIsPreventingShutdown; }
|
||||||
|
|
||||||
|
const char* Name() const { return mName; }
|
||||||
|
|
||||||
WorkerPrivate* mWorkerPrivate;
|
WorkerPrivate* mWorkerPrivate;
|
||||||
UniquePtr<WorkerHolder> mHolder;
|
|
||||||
|
|
||||||
std::function<void()> mCallback;
|
std::function<void()> mCallback;
|
||||||
|
const char* const mName;
|
||||||
|
const bool mIsPreventingShutdown;
|
||||||
|
|
||||||
|
// True if this WorkerRef has been added to a WorkerPrivate.
|
||||||
|
bool mHolding;
|
||||||
};
|
};
|
||||||
|
|
||||||
class WeakWorkerRef final : public WorkerRef {
|
class WeakWorkerRef final : public WorkerRef {
|
||||||
|
@ -171,7 +182,7 @@ class StrongWorkerRef final : public WorkerRef {
|
||||||
WorkerPrivate* aWorkerPrivate, const char* aName,
|
WorkerPrivate* aWorkerPrivate, const char* aName,
|
||||||
WorkerStatus aFailStatus);
|
WorkerStatus aFailStatus);
|
||||||
|
|
||||||
explicit StrongWorkerRef(WorkerPrivate* aWorkerPrivate);
|
StrongWorkerRef(WorkerPrivate* aWorkerPrivate, const char* aName);
|
||||||
~StrongWorkerRef();
|
~StrongWorkerRef();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -200,7 +211,7 @@ class IPCWorkerRef final : public WorkerRef {
|
||||||
WorkerPrivate* Private() const;
|
WorkerPrivate* Private() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit IPCWorkerRef(WorkerPrivate* aWorkerPrivate);
|
IPCWorkerRef(WorkerPrivate* aWorkerPrivate, const char* aName);
|
||||||
~IPCWorkerRef();
|
~IPCWorkerRef();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
#include "mozilla/dom/WorkerCommon.h"
|
#include "mozilla/dom/WorkerCommon.h"
|
||||||
#include "mozilla/dom/WorkerRef.h"
|
#include "mozilla/dom/WorkerRef.h"
|
||||||
|
#include "mozilla/dom/WorkerStatus.h"
|
||||||
|
|
||||||
#include "nsICancelableRunnable.h"
|
#include "nsICancelableRunnable.h"
|
||||||
|
|
||||||
|
|
|
@ -4,16 +4,12 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#ifndef mozilla_dom_workers_WorkerHolder_h
|
#ifndef mozilla_dom_workers_WorkerStatus_h
|
||||||
#define mozilla_dom_workers_WorkerHolder_h
|
#define mozilla_dom_workers_WorkerStatus_h
|
||||||
|
|
||||||
#include "mozilla/dom/WorkerCommon.h"
|
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace dom {
|
namespace dom {
|
||||||
|
|
||||||
class WorkerPrivate;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use this chart to help figure out behavior during each of the closing
|
* Use this chart to help figure out behavior during each of the closing
|
||||||
* statuses. Details below.
|
* statuses. Details below.
|
||||||
|
@ -40,9 +36,9 @@ enum WorkerStatus {
|
||||||
|
|
||||||
// Inner script called close() on the worker global scope. Setting this
|
// Inner script called close() on the worker global scope. Setting this
|
||||||
// status causes the worker to clear its queue of events but does not abort
|
// status causes the worker to clear its queue of events but does not abort
|
||||||
// the currently running script. WorkerHolder/WorkerRef objects are not going
|
// the currently running script. WorkerRef objects are not going to be
|
||||||
// to be notified because the behavior of APIs/Components should not change
|
// notified because the behavior of APIs/Components should not change during
|
||||||
// during this status yet.
|
// this status yet.
|
||||||
Closing,
|
Closing,
|
||||||
|
|
||||||
// Either the user navigated away from the owning page or the owning page fell
|
// Either the user navigated away from the owning page or the owning page fell
|
||||||
|
@ -58,42 +54,7 @@ enum WorkerStatus {
|
||||||
Dead
|
Dead
|
||||||
};
|
};
|
||||||
|
|
||||||
class WorkerHolder {
|
|
||||||
public:
|
|
||||||
enum Behavior {
|
|
||||||
AllowIdleShutdownStart,
|
|
||||||
PreventIdleShutdownStart,
|
|
||||||
};
|
|
||||||
|
|
||||||
explicit WorkerHolder(const char* aName,
|
|
||||||
Behavior aBehavior = PreventIdleShutdownStart);
|
|
||||||
virtual ~WorkerHolder();
|
|
||||||
|
|
||||||
bool HoldWorker(WorkerPrivate* aWorkerPrivate, WorkerStatus aFailStatus);
|
|
||||||
void ReleaseWorker();
|
|
||||||
|
|
||||||
virtual bool Notify(WorkerStatus aStatus) = 0;
|
|
||||||
|
|
||||||
Behavior GetBehavior() const;
|
|
||||||
|
|
||||||
const char* Name() const { return mName; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void ReleaseWorkerInternal();
|
|
||||||
|
|
||||||
WorkerPrivate* MOZ_NON_OWNING_REF mWorkerPrivate;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void AssertIsOwningThread() const;
|
|
||||||
|
|
||||||
const Behavior mBehavior;
|
|
||||||
|
|
||||||
// For debugging only.
|
|
||||||
void* mThread;
|
|
||||||
const char* mName;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
||||||
#endif /* mozilla_dom_workers_WorkerHolder_h */
|
#endif /* mozilla_dom_workers_WorkerStatus_h */
|
|
@ -17,7 +17,6 @@ EXPORTS.mozilla.dom += [
|
||||||
'WorkerDebugger.h',
|
'WorkerDebugger.h',
|
||||||
'WorkerDebuggerManager.h',
|
'WorkerDebuggerManager.h',
|
||||||
'WorkerError.h',
|
'WorkerError.h',
|
||||||
'WorkerHolder.h',
|
|
||||||
'WorkerLoadInfo.h',
|
'WorkerLoadInfo.h',
|
||||||
'WorkerLocation.h',
|
'WorkerLocation.h',
|
||||||
'WorkerNavigator.h',
|
'WorkerNavigator.h',
|
||||||
|
@ -25,6 +24,7 @@ EXPORTS.mozilla.dom += [
|
||||||
'WorkerRef.h',
|
'WorkerRef.h',
|
||||||
'WorkerRunnable.h',
|
'WorkerRunnable.h',
|
||||||
'WorkerScope.h',
|
'WorkerScope.h',
|
||||||
|
'WorkerStatus.h',
|
||||||
]
|
]
|
||||||
|
|
||||||
# Private stuff.
|
# Private stuff.
|
||||||
|
@ -56,7 +56,6 @@ UNIFIED_SOURCES += [
|
||||||
'WorkerDebuggerManager.cpp',
|
'WorkerDebuggerManager.cpp',
|
||||||
'WorkerError.cpp',
|
'WorkerError.cpp',
|
||||||
'WorkerEventTarget.cpp',
|
'WorkerEventTarget.cpp',
|
||||||
'WorkerHolder.cpp',
|
|
||||||
'WorkerLoadInfo.cpp',
|
'WorkerLoadInfo.cpp',
|
||||||
'WorkerLocation.cpp',
|
'WorkerLocation.cpp',
|
||||||
'WorkerNavigator.cpp',
|
'WorkerNavigator.cpp',
|
||||||
|
|
Загрузка…
Ссылка в новой задаче