Line data Source code
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/. */
6 :
7 : #include "mozilla/dom/cache/CacheChild.h"
8 :
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 :
14 : namespace mozilla {
15 : namespace dom {
16 : namespace cache {
17 :
18 : // Declared in ActorUtils.h
19 : PCacheChild*
20 0 : AllocPCacheChild()
21 : {
22 0 : return new CacheChild();
23 : }
24 :
25 : // Declared in ActorUtils.h
26 : void
27 0 : DeallocPCacheChild(PCacheChild* aActor)
28 : {
29 0 : delete aActor;
30 0 : }
31 :
32 0 : CacheChild::CacheChild()
33 : : mListener(nullptr)
34 : , mNumChildActors(0)
35 : , mDelayedDestroy(false)
36 0 : , mLocked(false)
37 : {
38 0 : MOZ_COUNT_CTOR(cache::CacheChild);
39 0 : }
40 :
41 0 : CacheChild::~CacheChild()
42 : {
43 0 : MOZ_COUNT_DTOR(cache::CacheChild);
44 0 : NS_ASSERT_OWNINGTHREAD(CacheChild);
45 0 : MOZ_DIAGNOSTIC_ASSERT(!mListener);
46 0 : MOZ_DIAGNOSTIC_ASSERT(!mNumChildActors);
47 0 : MOZ_DIAGNOSTIC_ASSERT(!mLocked);
48 0 : }
49 :
50 : void
51 0 : CacheChild::SetListener(Cache* aListener)
52 : {
53 0 : NS_ASSERT_OWNINGTHREAD(CacheChild);
54 0 : MOZ_DIAGNOSTIC_ASSERT(!mListener);
55 0 : mListener = aListener;
56 0 : MOZ_DIAGNOSTIC_ASSERT(mListener);
57 0 : }
58 :
59 : void
60 0 : CacheChild::ClearListener()
61 : {
62 0 : NS_ASSERT_OWNINGTHREAD(CacheChild);
63 0 : MOZ_DIAGNOSTIC_ASSERT(mListener);
64 0 : mListener = nullptr;
65 0 : }
66 :
67 : void
68 0 : CacheChild::ExecuteOp(nsIGlobalObject* aGlobal, Promise* aPromise,
69 : nsISupports* aParent, const CacheOpArgs& aArgs)
70 : {
71 0 : mNumChildActors += 1;
72 0 : MOZ_ALWAYS_TRUE(SendPCacheOpConstructor(
73 : new CacheOpChild(GetWorkerHolder(), aGlobal, aParent, aPromise), aArgs));
74 0 : }
75 :
76 : void
77 0 : CacheChild::StartDestroyFromListener()
78 : {
79 0 : NS_ASSERT_OWNINGTHREAD(CacheChild);
80 :
81 : // The listener should be held alive by any async operations, so if it
82 : // is going away then there must not be any child actors. This in turn
83 : // ensures that StartDestroy() will not trigger the delayed path.
84 0 : MOZ_DIAGNOSTIC_ASSERT(!mNumChildActors);
85 :
86 0 : StartDestroy();
87 0 : }
88 :
89 : void
90 0 : CacheChild::StartDestroy()
91 : {
92 0 : NS_ASSERT_OWNINGTHREAD(CacheChild);
93 :
94 : // If we have outstanding child actors, then don't destroy ourself yet.
95 : // The child actors should be short lived and we should allow them to complete
96 : // if possible. NoteDeletedActor() will call back into this Shutdown()
97 : // method when the last child actor is gone. Also, delay destruction if we
98 : // have been explicitly locked by someone using us on the stack.
99 0 : if (mNumChildActors || mLocked) {
100 0 : mDelayedDestroy = true;
101 0 : return;
102 : }
103 :
104 0 : RefPtr<Cache> listener = mListener;
105 :
106 : // StartDestroy() can get called from either Cache or the WorkerHolder.
107 : // Theoretically we can get double called if the right race happens. Handle
108 : // that by just ignoring the second StartDestroy() call.
109 0 : if (!listener) {
110 0 : return;
111 : }
112 :
113 0 : listener->DestroyInternal(this);
114 :
115 : // Cache listener should call ClearListener() in DestroyInternal()
116 0 : MOZ_DIAGNOSTIC_ASSERT(!mListener);
117 :
118 : // Start actor destruction from parent process
119 0 : Unused << SendTeardown();
120 : }
121 :
122 : void
123 0 : CacheChild::ActorDestroy(ActorDestroyReason aReason)
124 : {
125 0 : NS_ASSERT_OWNINGTHREAD(CacheChild);
126 0 : RefPtr<Cache> listener = mListener;
127 0 : if (listener) {
128 0 : listener->DestroyInternal(this);
129 : // Cache listener should call ClearListener() in DestroyInternal()
130 0 : MOZ_DIAGNOSTIC_ASSERT(!mListener);
131 : }
132 :
133 0 : RemoveWorkerHolder();
134 0 : }
135 :
136 : PCacheOpChild*
137 0 : CacheChild::AllocPCacheOpChild(const CacheOpArgs& aOpArgs)
138 : {
139 0 : MOZ_CRASH("CacheOpChild should be manually constructed.");
140 : return nullptr;
141 : }
142 :
143 : bool
144 0 : CacheChild::DeallocPCacheOpChild(PCacheOpChild* aActor)
145 : {
146 0 : delete aActor;
147 0 : NoteDeletedActor();
148 0 : return true;
149 : }
150 :
151 : void
152 0 : CacheChild::NoteDeletedActor()
153 : {
154 0 : mNumChildActors -= 1;
155 0 : MaybeFlushDelayedDestroy();
156 0 : }
157 :
158 : void
159 0 : CacheChild::MaybeFlushDelayedDestroy()
160 : {
161 0 : if (!mNumChildActors && !mLocked && mDelayedDestroy) {
162 0 : StartDestroy();
163 : }
164 0 : }
165 :
166 : void
167 0 : CacheChild::Lock()
168 : {
169 0 : NS_ASSERT_OWNINGTHREAD(CacheChild);
170 0 : MOZ_DIAGNOSTIC_ASSERT(!mLocked);
171 0 : mLocked = true;
172 0 : }
173 :
174 : void
175 0 : CacheChild::Unlock()
176 : {
177 0 : NS_ASSERT_OWNINGTHREAD(CacheChild);
178 0 : MOZ_DIAGNOSTIC_ASSERT(mLocked);
179 0 : mLocked = false;
180 0 : MaybeFlushDelayedDestroy();
181 0 : }
182 :
183 : } // namespace cache
184 : } // namespace dom
185 : } // namespace mozilla
|