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:
Andrea Marchesini 2019-07-12 11:18:17 +00:00
Родитель 46c41f3318
Коммит 2a3e21430e
8 изменённых файлов: 125 добавлений и 227 удалений

Просмотреть файл

@ -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',