Bug 1688354 [wpt PR 27298] - Treat 'rem' as an absolute unit for font size, a=testonly
[gecko.git] / dom / workers / WorkerRef.cpp
blob7669a8ae5578458023988f0ce4272b28fa376254
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "mozilla/dom/WorkerRef.h"
9 #include "nsDebug.h"
10 #include "WorkerRunnable.h"
11 #include "WorkerPrivate.h"
13 namespace mozilla {
14 namespace dom {
16 namespace {
18 // This runnable is used to release the StrongWorkerRef on the worker thread
19 // when a ThreadSafeWorkerRef is released.
20 class ReleaseRefControlRunnable final : public WorkerControlRunnable {
21 public:
22 ReleaseRefControlRunnable(WorkerPrivate* aWorkerPrivate,
23 already_AddRefed<StrongWorkerRef> aRef)
24 : WorkerControlRunnable(aWorkerPrivate, WorkerThreadUnchangedBusyCount),
25 mRef(std::move(aRef)) {
26 MOZ_ASSERT(mRef);
29 bool PreDispatch(WorkerPrivate* aWorkerPrivate) override { return true; }
31 void PostDispatch(WorkerPrivate* aWorkerPrivate,
32 bool aDispatchResult) override {}
34 bool WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override {
35 mRef = nullptr;
36 return true;
39 private:
40 RefPtr<StrongWorkerRef> mRef;
43 } // namespace
45 // ----------------------------------------------------------------------------
46 // WorkerRef
48 WorkerRef::WorkerRef(WorkerPrivate* aWorkerPrivate, const char* aName,
49 bool aIsPreventingShutdown)
50 : mWorkerPrivate(aWorkerPrivate),
51 mName(aName),
52 mIsPreventingShutdown(aIsPreventingShutdown),
53 mHolding(false) {
54 MOZ_ASSERT(aWorkerPrivate);
55 MOZ_ASSERT(aName);
57 aWorkerPrivate->AssertIsOnWorkerThread();
60 WorkerRef::~WorkerRef() {
61 NS_ASSERT_OWNINGTHREAD(WorkerRef);
62 ReleaseWorker();
65 void WorkerRef::ReleaseWorker() {
66 if (mHolding) {
67 MOZ_ASSERT(mWorkerPrivate);
69 mWorkerPrivate->RemoveWorkerRef(this);
70 mWorkerPrivate = nullptr;
72 mHolding = false;
76 bool WorkerRef::HoldWorker(WorkerStatus aStatus) {
77 MOZ_ASSERT(mWorkerPrivate);
78 MOZ_ASSERT(!mHolding);
80 if (NS_WARN_IF(!mWorkerPrivate->AddWorkerRef(this, aStatus))) {
81 return false;
84 mHolding = true;
85 return true;
88 void WorkerRef::Notify() {
89 NS_ASSERT_OWNINGTHREAD(WorkerRef);
91 if (!mCallback) {
92 return;
95 std::function<void()> callback = std::move(mCallback);
96 MOZ_ASSERT(!mCallback);
98 callback();
101 // ----------------------------------------------------------------------------
102 // WeakWorkerRef
104 /* static */
105 already_AddRefed<WeakWorkerRef> WeakWorkerRef::Create(
106 WorkerPrivate* aWorkerPrivate, std::function<void()>&& aCallback) {
107 MOZ_ASSERT(aWorkerPrivate);
108 aWorkerPrivate->AssertIsOnWorkerThread();
110 RefPtr<WeakWorkerRef> ref = new WeakWorkerRef(aWorkerPrivate);
111 if (!ref->HoldWorker(Canceling)) {
112 return nullptr;
115 ref->mCallback = std::move(aCallback);
117 return ref.forget();
120 WeakWorkerRef::WeakWorkerRef(WorkerPrivate* aWorkerPrivate)
121 : WorkerRef(aWorkerPrivate, "WeakWorkerRef", false) {}
123 WeakWorkerRef::~WeakWorkerRef() = default;
125 void WeakWorkerRef::Notify() {
126 MOZ_ASSERT(mHolding);
127 MOZ_ASSERT(mWorkerPrivate);
129 // Notify could drop the last reference to this object. We must keep it alive
130 // in order to call ReleaseWorker() immediately after.
131 RefPtr<WeakWorkerRef> kungFuGrip = this;
133 WorkerRef::Notify();
134 ReleaseWorker();
137 WorkerPrivate* WeakWorkerRef::GetPrivate() const {
138 NS_ASSERT_OWNINGTHREAD(WeakWorkerRef);
139 return mWorkerPrivate;
142 WorkerPrivate* WeakWorkerRef::GetUnsafePrivate() const {
143 return mWorkerPrivate;
146 // ----------------------------------------------------------------------------
147 // StrongWorkerRef
149 /* static */
150 already_AddRefed<StrongWorkerRef> StrongWorkerRef::Create(
151 WorkerPrivate* const aWorkerPrivate, const char* const aName,
152 std::function<void()>&& aCallback) {
153 if (RefPtr<StrongWorkerRef> ref =
154 CreateImpl(aWorkerPrivate, aName, Canceling)) {
155 ref->mCallback = std::move(aCallback);
156 return ref.forget();
158 return nullptr;
161 /* static */
162 already_AddRefed<StrongWorkerRef> StrongWorkerRef::CreateForcibly(
163 WorkerPrivate* const aWorkerPrivate, const char* const aName) {
164 return CreateImpl(aWorkerPrivate, aName, Killing);
167 /* static */
168 already_AddRefed<StrongWorkerRef> StrongWorkerRef::CreateImpl(
169 WorkerPrivate* const aWorkerPrivate, const char* const aName,
170 WorkerStatus const aFailStatus) {
171 MOZ_ASSERT(aWorkerPrivate);
172 MOZ_ASSERT(aName);
174 RefPtr<StrongWorkerRef> ref = new StrongWorkerRef(aWorkerPrivate, aName);
175 if (!ref->HoldWorker(aFailStatus)) {
176 return nullptr;
179 return ref.forget();
182 StrongWorkerRef::StrongWorkerRef(WorkerPrivate* aWorkerPrivate,
183 const char* aName)
184 : WorkerRef(aWorkerPrivate, aName, true) {}
186 StrongWorkerRef::~StrongWorkerRef() = default;
188 WorkerPrivate* StrongWorkerRef::Private() const {
189 NS_ASSERT_OWNINGTHREAD(StrongWorkerRef);
190 return mWorkerPrivate;
193 // ----------------------------------------------------------------------------
194 // ThreadSafeWorkerRef
196 ThreadSafeWorkerRef::ThreadSafeWorkerRef(StrongWorkerRef* aRef) : mRef(aRef) {
197 MOZ_ASSERT(aRef);
198 aRef->Private()->AssertIsOnWorkerThread();
201 ThreadSafeWorkerRef::~ThreadSafeWorkerRef() {
202 // Let's release the StrongWorkerRef on the correct thread.
203 if (!mRef->mWorkerPrivate->IsOnWorkerThread()) {
204 WorkerPrivate* workerPrivate = mRef->mWorkerPrivate;
205 RefPtr<ReleaseRefControlRunnable> r =
206 new ReleaseRefControlRunnable(workerPrivate, mRef.forget());
207 r->Dispatch();
208 return;
212 WorkerPrivate* ThreadSafeWorkerRef::Private() const {
213 return mRef->mWorkerPrivate;
216 // ----------------------------------------------------------------------------
217 // IPCWorkerRef
219 /* static */
220 already_AddRefed<IPCWorkerRef> IPCWorkerRef::Create(
221 WorkerPrivate* aWorkerPrivate, const char* aName,
222 std::function<void()>&& aCallback) {
223 MOZ_ASSERT(aWorkerPrivate);
224 aWorkerPrivate->AssertIsOnWorkerThread();
226 RefPtr<IPCWorkerRef> ref = new IPCWorkerRef(aWorkerPrivate, aName);
227 if (!ref->HoldWorker(Canceling)) {
228 return nullptr;
231 ref->mCallback = std::move(aCallback);
233 return ref.forget();
236 IPCWorkerRef::IPCWorkerRef(WorkerPrivate* aWorkerPrivate, const char* aName)
237 : WorkerRef(aWorkerPrivate, aName, false) {}
239 IPCWorkerRef::~IPCWorkerRef() = default;
241 WorkerPrivate* IPCWorkerRef::Private() const {
242 NS_ASSERT_OWNINGTHREAD(IPCWorkerRef);
243 return mWorkerPrivate;
246 } // namespace dom
247 } // namespace mozilla