CacheWorkerRef.cpp (4073B)
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/CacheWorkerRef.h" 8 9 #include "mozilla/dom/WorkerPrivate.h" 10 #include "mozilla/dom/WorkerRef.h" 11 #include "mozilla/dom/cache/ActorChild.h" 12 13 namespace mozilla::dom::cache { 14 15 // static 16 SafeRefPtr<CacheWorkerRef> CacheWorkerRef::Create(WorkerPrivate* aWorkerPrivate, 17 Behavior aBehavior) { 18 MOZ_DIAGNOSTIC_ASSERT(aWorkerPrivate); 19 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 22 auto workerRef = 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)); 28 } else { 29 MOZ_ASSERT(aBehavior == eIPCWorkerRef); 30 workerRef->mIPCWorkerRef = IPCWorkerRef::Create( 31 aWorkerPrivate, "CacheWorkerRef-IPC", std::move(notify)); 32 } 33 34 if (NS_WARN_IF(!workerRef->mIPCWorkerRef && !workerRef->mStrongWorkerRef)) { 35 return nullptr; 36 } 37 38 return workerRef; 39 } 40 41 // static 42 SafeRefPtr<CacheWorkerRef> CacheWorkerRef::PreferBehavior( 43 SafeRefPtr<CacheWorkerRef> aCurrentRef, Behavior aBehavior) { 44 if (!aCurrentRef) { 45 return nullptr; 46 } 47 48 SafeRefPtr<CacheWorkerRef> orig = std::move(aCurrentRef); 49 if (orig->mBehavior == aBehavior) { 50 return orig; 51 } 52 53 WorkerPrivate* workerPrivate = nullptr; 54 if (orig->mBehavior == eStrongWorkerRef) { 55 workerPrivate = orig->mStrongWorkerRef->Private(); 56 } else { 57 MOZ_ASSERT(orig->mBehavior == eIPCWorkerRef); 58 workerPrivate = orig->mIPCWorkerRef->Private(); 59 } 60 61 MOZ_ASSERT(workerPrivate); 62 63 SafeRefPtr<CacheWorkerRef> replace = Create(workerPrivate, aBehavior); 64 return static_cast<bool>(replace) ? std::move(replace) : std::move(orig); 65 } 66 67 void CacheWorkerRef::AddActor(ActorChild& aActor) { 68 NS_ASSERT_OWNINGTHREAD(CacheWorkerRef); 69 MOZ_ASSERT(!mActorList.Contains(&aActor)); 70 71 mActorList.AppendElement(WrapNotNullUnchecked(&aActor)); 72 if (mBehavior == eIPCWorkerRef) { 73 MOZ_ASSERT(mIPCWorkerRef); 74 mIPCWorkerRef->SetActorCount(mActorList.Length()); 75 } 76 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. 81 if (mNotified) { 82 aActor.StartDestroy(); 83 } 84 } 85 86 void CacheWorkerRef::RemoveActor(ActorChild& aActor) { 87 NS_ASSERT_OWNINGTHREAD(CacheWorkerRef); 88 89 #if defined(RELEASE_OR_BETA) 90 mActorList.RemoveElement(&aActor); 91 #else 92 MOZ_DIAGNOSTIC_ASSERT(mActorList.RemoveElement(&aActor)); 93 #endif 94 95 MOZ_ASSERT(!mActorList.Contains(&aActor)); 96 97 if (mBehavior == eIPCWorkerRef) { 98 MOZ_ASSERT(mIPCWorkerRef); 99 mIPCWorkerRef->SetActorCount(mActorList.Length()); 100 } 101 102 if (mActorList.IsEmpty()) { 103 mStrongWorkerRef = nullptr; 104 mIPCWorkerRef = nullptr; 105 } 106 } 107 108 bool CacheWorkerRef::Notified() const { return mNotified; } 109 110 void CacheWorkerRef::Notify() { 111 NS_ASSERT_OWNINGTHREAD(CacheWorkerRef); 112 113 mNotified = true; 114 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(); 119 } 120 } 121 122 CacheWorkerRef::CacheWorkerRef(Behavior aBehavior, ConstructorGuard) 123 : mBehavior(aBehavior), mNotified(false) {} 124 125 CacheWorkerRef::~CacheWorkerRef() { 126 NS_ASSERT_OWNINGTHREAD(CacheWorkerRef); 127 MOZ_DIAGNOSTIC_ASSERT(mActorList.IsEmpty()); 128 } 129 130 } // namespace mozilla::dom::cache