Source code
Revision control
Copy as Markdown
Other Tools
/* -*- 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
#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 <typename ActorType>
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 <typename Callable>
void MaybeExecute(
const Callable& aSuccess, const std::function<void()>& 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