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/cache/CacheWorkerRef.h"
9 #include "mozilla/dom/cache/ActorChild.h"
10 #include "mozilla/dom/WorkerPrivate.h"
11 #include "mozilla/dom/WorkerRef.h"
13 namespace mozilla::dom::cache
{
16 SafeRefPtr
<CacheWorkerRef
> CacheWorkerRef::Create(WorkerPrivate
* aWorkerPrivate
,
18 MOZ_DIAGNOSTIC_ASSERT(aWorkerPrivate
);
20 // XXX This looks as if this could be simplified now by moving into the ctor
21 // of CacheWorkerRef, since we can now use SafeRefPtrFromThis in the ctor
23 MakeSafeRefPtr
<CacheWorkerRef
>(aBehavior
, ConstructorGuard
{});
24 auto notify
= [workerRef
= workerRef
.clonePtr()] { workerRef
->Notify(); };
25 if (aBehavior
== eStrongWorkerRef
) {
26 workerRef
->mStrongWorkerRef
= StrongWorkerRef::Create(
27 aWorkerPrivate
, "CacheWorkerRef-Strong", std::move(notify
));
29 MOZ_ASSERT(aBehavior
== eIPCWorkerRef
);
30 workerRef
->mIPCWorkerRef
= IPCWorkerRef::Create(
31 aWorkerPrivate
, "CacheWorkerRef-IPC", std::move(notify
));
34 if (NS_WARN_IF(!workerRef
->mIPCWorkerRef
&& !workerRef
->mStrongWorkerRef
)) {
42 SafeRefPtr
<CacheWorkerRef
> CacheWorkerRef::PreferBehavior(
43 SafeRefPtr
<CacheWorkerRef
> aCurrentRef
, Behavior aBehavior
) {
48 SafeRefPtr
<CacheWorkerRef
> orig
= std::move(aCurrentRef
);
49 if (orig
->mBehavior
== aBehavior
) {
53 WorkerPrivate
* workerPrivate
= nullptr;
54 if (orig
->mBehavior
== eStrongWorkerRef
) {
55 workerPrivate
= orig
->mStrongWorkerRef
->Private();
57 MOZ_ASSERT(orig
->mBehavior
== eIPCWorkerRef
);
58 workerPrivate
= orig
->mIPCWorkerRef
->Private();
61 MOZ_ASSERT(workerPrivate
);
63 SafeRefPtr
<CacheWorkerRef
> replace
= Create(workerPrivate
, aBehavior
);
64 return static_cast<bool>(replace
) ? std::move(replace
) : std::move(orig
);
67 void CacheWorkerRef::AddActor(ActorChild
& aActor
) {
68 NS_ASSERT_OWNINGTHREAD(CacheWorkerRef
);
69 MOZ_ASSERT(!mActorList
.Contains(&aActor
));
71 mActorList
.AppendElement(WrapNotNullUnchecked(&aActor
));
72 if (mBehavior
== eIPCWorkerRef
) {
73 MOZ_ASSERT(mIPCWorkerRef
);
74 mIPCWorkerRef
->SetActorCount(mActorList
.Length());
77 // Allow an actor to be added after we've entered the Notifying case. We
78 // can't stop the actor creation from racing with out destruction of the
79 // other actors and we need to wait for this extra one to close as well.
80 // Signal it should destroy itself right away.
82 aActor
.StartDestroy();
86 void CacheWorkerRef::RemoveActor(ActorChild
& aActor
) {
87 NS_ASSERT_OWNINGTHREAD(CacheWorkerRef
);
89 #if defined(RELEASE_OR_BETA)
90 mActorList
.RemoveElement(&aActor
);
92 MOZ_DIAGNOSTIC_ASSERT(mActorList
.RemoveElement(&aActor
));
95 MOZ_ASSERT(!mActorList
.Contains(&aActor
));
97 if (mBehavior
== eIPCWorkerRef
) {
98 MOZ_ASSERT(mIPCWorkerRef
);
99 mIPCWorkerRef
->SetActorCount(mActorList
.Length());
102 if (mActorList
.IsEmpty()) {
103 mStrongWorkerRef
= nullptr;
104 mIPCWorkerRef
= nullptr;
108 bool CacheWorkerRef::Notified() const { return mNotified
; }
110 void CacheWorkerRef::Notify() {
111 NS_ASSERT_OWNINGTHREAD(CacheWorkerRef
);
115 // Start the asynchronous destruction of our actors. These will call back
116 // into RemoveActor() once the actor is destroyed.
117 for (const auto& actor
: mActorList
) {
118 actor
->StartDestroy();
122 CacheWorkerRef::CacheWorkerRef(Behavior aBehavior
, ConstructorGuard
)
123 : mBehavior(aBehavior
), mNotified(false) {}
125 CacheWorkerRef::~CacheWorkerRef() {
126 NS_ASSERT_OWNINGTHREAD(CacheWorkerRef
);
127 MOZ_DIAGNOSTIC_ASSERT(mActorList
.IsEmpty());
130 } // namespace mozilla::dom::cache