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 // XXX Move this to mfbt, or do we already have something like this? Or remove
17 // the need for that by changing StrongWorkerRef/IPCWorkerRef?
22 explicit FakeCopyable(T
&& aTarget
) : mTarget(std::forward
<T
>(aTarget
)) {}
24 FakeCopyable(FakeCopyable
&&) = default;
26 FakeCopyable(const FakeCopyable
& aOther
)
27 : mTarget(std::move(const_cast<FakeCopyable
&>(aOther
).mTarget
)) {
28 MOZ_CRASH("Do not copy.");
31 template <typename
... Args
>
32 auto operator()(Args
&&... aArgs
) {
33 return mTarget(std::forward
<Args
>(aArgs
)...);
43 SafeRefPtr
<CacheWorkerRef
> CacheWorkerRef::Create(WorkerPrivate
* aWorkerPrivate
,
45 MOZ_DIAGNOSTIC_ASSERT(aWorkerPrivate
);
47 // XXX This looks as if this could be simplified now by moving into the ctor
48 // of CacheWorkerRef, since we can now use SafeRefPtrFromThis in the ctor
50 MakeSafeRefPtr
<CacheWorkerRef
>(aBehavior
, ConstructorGuard
{});
52 FakeCopyable([workerRef
= workerRef
.clonePtr()] { workerRef
->Notify(); });
53 if (aBehavior
== eStrongWorkerRef
) {
54 workerRef
->mStrongWorkerRef
= StrongWorkerRef::Create(
55 aWorkerPrivate
, "CacheWorkerRef-Strong", std::move(notify
));
57 MOZ_ASSERT(aBehavior
== eIPCWorkerRef
);
58 workerRef
->mIPCWorkerRef
= IPCWorkerRef::Create(
59 aWorkerPrivate
, "CacheWorkerRef-IPC", std::move(notify
));
62 if (NS_WARN_IF(!workerRef
->mIPCWorkerRef
&& !workerRef
->mStrongWorkerRef
)) {
70 SafeRefPtr
<CacheWorkerRef
> CacheWorkerRef::PreferBehavior(
71 SafeRefPtr
<CacheWorkerRef
> aCurrentRef
, Behavior aBehavior
) {
76 SafeRefPtr
<CacheWorkerRef
> orig
= std::move(aCurrentRef
);
77 if (orig
->mBehavior
== aBehavior
) {
81 WorkerPrivate
* workerPrivate
= nullptr;
82 if (orig
->mBehavior
== eStrongWorkerRef
) {
83 workerPrivate
= orig
->mStrongWorkerRef
->Private();
85 MOZ_ASSERT(orig
->mBehavior
== eIPCWorkerRef
);
86 workerPrivate
= orig
->mIPCWorkerRef
->Private();
89 MOZ_ASSERT(workerPrivate
);
91 SafeRefPtr
<CacheWorkerRef
> replace
= Create(workerPrivate
, aBehavior
);
92 return static_cast<bool>(replace
) ? std::move(replace
) : std::move(orig
);
95 void CacheWorkerRef::AddActor(ActorChild
& aActor
) {
96 NS_ASSERT_OWNINGTHREAD(CacheWorkerRef
);
97 MOZ_ASSERT(!mActorList
.Contains(&aActor
));
99 mActorList
.AppendElement(WrapNotNullUnchecked(&aActor
));
101 // Allow an actor to be added after we've entered the Notifying case. We
102 // can't stop the actor creation from racing with out destruction of the
103 // other actors and we need to wait for this extra one to close as well.
104 // Signal it should destroy itself right away.
106 aActor
.StartDestroy();
110 void CacheWorkerRef::RemoveActor(ActorChild
& aActor
) {
111 NS_ASSERT_OWNINGTHREAD(CacheWorkerRef
);
113 #if defined(RELEASE_OR_BETA)
114 mActorList
.RemoveElement(&aActor
);
116 MOZ_DIAGNOSTIC_ASSERT(mActorList
.RemoveElement(&aActor
));
119 MOZ_ASSERT(!mActorList
.Contains(&aActor
));
121 if (mActorList
.IsEmpty()) {
122 mStrongWorkerRef
= nullptr;
123 mIPCWorkerRef
= nullptr;
127 bool CacheWorkerRef::Notified() const { return mNotified
; }
129 void CacheWorkerRef::Notify() {
130 NS_ASSERT_OWNINGTHREAD(CacheWorkerRef
);
134 // Start the asynchronous destruction of our actors. These will call back
135 // into RemoveActor() once the actor is destroyed.
136 for (const auto& actor
: mActorList
) {
137 actor
->StartDestroy();
141 CacheWorkerRef::CacheWorkerRef(Behavior aBehavior
, ConstructorGuard
)
142 : mBehavior(aBehavior
), mNotified(false) {}
144 CacheWorkerRef::~CacheWorkerRef() {
145 NS_ASSERT_OWNINGTHREAD(CacheWorkerRef
);
146 MOZ_DIAGNOSTIC_ASSERT(mActorList
.IsEmpty());
149 } // namespace mozilla::dom::cache