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/CacheChild.h"
9 #include "mozilla/Unused.h"
10 #include "mozilla/dom/cache/ActorUtils.h"
11 #include "mozilla/dom/cache/Cache.h"
12 #include "mozilla/dom/cache/CacheOpChild.h"
13 #include "CacheWorkerRef.h"
15 namespace mozilla::dom::cache
{
17 // Declared in ActorUtils.h
18 PCacheChild
* AllocPCacheChild() { return new CacheChild(); }
20 // Declared in ActorUtils.h
21 void DeallocPCacheChild(PCacheChild
* aActor
) { delete aActor
; }
23 CacheChild::CacheChild()
26 mDelayedDestroy(false),
28 MOZ_COUNT_CTOR(cache::CacheChild
);
31 CacheChild::~CacheChild() {
32 MOZ_COUNT_DTOR(cache::CacheChild
);
33 NS_ASSERT_OWNINGTHREAD(CacheChild
);
34 MOZ_DIAGNOSTIC_ASSERT(!mListener
);
35 MOZ_DIAGNOSTIC_ASSERT(!mNumChildActors
);
36 MOZ_DIAGNOSTIC_ASSERT(!mLocked
);
39 void CacheChild::SetListener(Cache
* aListener
) {
40 NS_ASSERT_OWNINGTHREAD(CacheChild
);
41 MOZ_DIAGNOSTIC_ASSERT(!mListener
);
42 mListener
= aListener
;
43 MOZ_DIAGNOSTIC_ASSERT(mListener
);
46 void CacheChild::ClearListener() {
47 NS_ASSERT_OWNINGTHREAD(CacheChild
);
48 MOZ_DIAGNOSTIC_ASSERT(mListener
);
52 void CacheChild::ExecuteOp(nsIGlobalObject
* aGlobal
, Promise
* aPromise
,
53 nsISupports
* aParent
, const CacheOpArgs
& aArgs
) {
56 SendPCacheOpConstructor(new CacheOpChild(GetWorkerRefPtr().clonePtr(),
57 aGlobal
, aParent
, aPromise
),
61 void CacheChild::StartDestroyFromListener() {
62 NS_ASSERT_OWNINGTHREAD(CacheChild
);
64 // The listener should be held alive by any async operations, so if it
65 // is going away then there must not be any child actors. This in turn
66 // ensures that StartDestroy() will not trigger the delayed path.
67 MOZ_DIAGNOSTIC_ASSERT(!mNumChildActors
);
72 void CacheChild::StartDestroy() {
73 NS_ASSERT_OWNINGTHREAD(CacheChild
);
75 // If we have outstanding child actors, then don't destroy ourself yet.
76 // The child actors should be short lived and we should allow them to complete
77 // if possible. NoteDeletedActor() will call back into this Shutdown()
78 // method when the last child actor is gone. Also, delay destruction if we
79 // have been explicitly locked by someone using us on the stack.
80 if (mNumChildActors
|| mLocked
) {
81 mDelayedDestroy
= true;
85 RefPtr
<Cache
> listener
= mListener
;
87 // StartDestroy() can get called from either Cache or the WorkerRef.
88 // Theoretically we can get double called if the right race happens. Handle
89 // that by just ignoring the second StartDestroy() call.
94 listener
->DestroyInternal(this);
96 // Cache listener should call ClearListener() in DestroyInternal()
97 MOZ_DIAGNOSTIC_ASSERT(!mListener
);
99 // Start actor destruction from parent process
100 Unused
<< SendTeardown();
103 void CacheChild::ActorDestroy(ActorDestroyReason aReason
) {
104 NS_ASSERT_OWNINGTHREAD(CacheChild
);
105 RefPtr
<Cache
> listener
= mListener
;
107 listener
->DestroyInternal(this);
108 // Cache listener should call ClearListener() in DestroyInternal()
109 MOZ_DIAGNOSTIC_ASSERT(!mListener
);
115 PCacheOpChild
* CacheChild::AllocPCacheOpChild(const CacheOpArgs
& aOpArgs
) {
116 MOZ_CRASH("CacheOpChild should be manually constructed.");
120 bool CacheChild::DeallocPCacheOpChild(PCacheOpChild
* aActor
) {
126 void CacheChild::NoteDeletedActor() {
127 mNumChildActors
-= 1;
128 MaybeFlushDelayedDestroy();
131 void CacheChild::MaybeFlushDelayedDestroy() {
132 if (!mNumChildActors
&& !mLocked
&& mDelayedDestroy
) {
137 void CacheChild::Lock() {
138 NS_ASSERT_OWNINGTHREAD(CacheChild
);
139 MOZ_DIAGNOSTIC_ASSERT(!mLocked
);
143 void CacheChild::Unlock() {
144 NS_ASSERT_OWNINGTHREAD(CacheChild
);
145 MOZ_DIAGNOSTIC_ASSERT(mLocked
);
147 MaybeFlushDelayedDestroy();
150 } // namespace mozilla::dom::cache