/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef _mozilla_dom_ClientThing_h #define _mozilla_dom_ClientThing_h #include "nsTArray.h" namespace mozilla::dom { // Base class representing various Client "things" such as ClientHandle, // ClientSource, and ClientManager. Currently it provides a common set // of code for handling activation and shutdown of IPC actors. template class ClientThing { #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED static const uint32_t kMagic1 = 0xC9FE2C9C; static const uint32_t kMagic2 = 0x832072D4; #endif ActorType* mActor; #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED uint32_t mMagic1; uint32_t mMagic2; #endif bool mShutdown; protected: ClientThing() : mActor(nullptr) #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED , mMagic1(kMagic1), mMagic2(kMagic2) #endif , mShutdown(false) { } ~ClientThing() { AssertIsValid(); ShutdownThing(); #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED mMagic1 = 0; mMagic2 = 0; #endif } void AssertIsValid() const { MOZ_DIAGNOSTIC_ASSERT(mMagic1 == kMagic1); MOZ_DIAGNOSTIC_ASSERT(mMagic2 == kMagic2); } // Return the current actor. ActorType* GetActor() const { AssertIsValid(); return mActor; } // Returns true if ShutdownThing() has been called. bool IsShutdown() const { AssertIsValid(); return mShutdown; } // Conditionally execute the given callable based on the current state. template void MaybeExecute( const Callable& aSuccess, const std::function& aFailure = [] {}) { AssertIsValid(); if (mShutdown) { aFailure(); return; } MOZ_DIAGNOSTIC_ASSERT(mActor); aSuccess(mActor); } // Attach activate the thing by attaching its underlying IPC actor. This // will make the thing register as the actor's owner as well. The actor // must call RevokeActor() to clear this weak back reference before its // destroyed. void ActivateThing(ActorType* aActor) { AssertIsValid(); MOZ_DIAGNOSTIC_ASSERT(aActor); MOZ_DIAGNOSTIC_ASSERT(!mActor); MOZ_DIAGNOSTIC_ASSERT(!mShutdown); mActor = aActor; mActor->SetOwner(this); } // Start destroying the underlying actor and disconnect the thing. void ShutdownThing() { AssertIsValid(); if (mShutdown) { return; } mShutdown = true; // If we are shutdown before the actor, then clear the weak references // between the actor and the thing. if (mActor) { mActor->RevokeOwner(this); mActor->MaybeStartTeardown(); mActor = nullptr; } OnShutdownThing(); } // Allow extending classes to take action when shutdown. virtual void OnShutdownThing() { // by default do nothing } public: // Clear the weak references between the thing and its IPC actor. void RevokeActor(ActorType* aActor) { AssertIsValid(); MOZ_DIAGNOSTIC_ASSERT(mActor); MOZ_DIAGNOSTIC_ASSERT(mActor == aActor); mActor->RevokeOwner(this); mActor = nullptr; // Also consider the ClientThing shutdown. We simply set the flag // instead of calling ShutdownThing() to avoid calling MaybeStartTeardown() // on the destroyed actor. mShutdown = true; OnShutdownThing(); } }; } // namespace mozilla::dom #endif // _mozilla_dom_ClientThing_h