/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- * 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/. */ /* smart pointer for strong references to objects through pointer-like * "handle" objects */ #include #include "mozilla/Assertions.h" #ifndef mozilla_HandleRefPtr_h #define mozilla_HandleRefPtr_h namespace mozilla { /** * A class for holding strong references to handle-managed objects. * * This is intended for use with objects like RestyleManagerHandle, * where the handle type is not a pointer but which can still have * ->AddRef() and ->Release() called on it. */ template class HandleRefPtr { public: HandleRefPtr() {} HandleRefPtr(HandleRefPtr& aRhs) { assign(aRhs.mHandle); } HandleRefPtr(HandleRefPtr&& aRhs) { std::swap(mHandle, aRhs.mHandle); } MOZ_IMPLICIT HandleRefPtr(T aRhs) { assign(aRhs); } HandleRefPtr& operator=(HandleRefPtr& aRhs) { assign(aRhs.mHandle); return *this; } HandleRefPtr& operator=(T aRhs) { assign(aRhs); return *this; } ~HandleRefPtr() { assign(nullptr); } explicit operator bool() const { return !!mHandle; } bool operator!() const { return !mHandle; } operator T() const { return mHandle; } T operator->() const { return mHandle; } void swap(HandleRefPtr& aOther) { std::swap(mHandle, aOther.mHandle); } private: void assign(T aPtr) { // AddRef early so |aPtr| can't disappear underneath us. if (aPtr) { aPtr->AddRef(); } // Don't release |mHandle| yet: if |mHandle| indirectly owns |this|, // releasing would invalidate |this|. Swap |aPtr| for |mHandle| so that // |aPtr| lives as long as |this|, then release the new |aPtr| (really the // original |mHandle|) so that if |this| is invalidated, we're not using it // any more. std::swap(mHandle, aPtr); if (aPtr) { aPtr->Release(); } } T mHandle; }; template inline bool operator==(const HandleRefPtr& aLHS, const HandleRefPtr& aRHS) { return static_cast(aLHS) == static_cast(aRHS); } template inline bool operator==(const HandleRefPtr& aLHS, T aRHS) { return static_cast(aLHS) == aRHS; } template inline bool operator==(T aLHS, const HandleRefPtr& aRHS) { return aLHS == static_cast(aRHS); } template inline bool operator!=(const HandleRefPtr& aLHS, const HandleRefPtr& aRHS) { return !(aLHS == aRHS); } template inline bool operator!=(const HandleRefPtr& aLHS, T aRHS) { return !(aLHS == aRHS); } template inline bool operator!=(T aLHS, const HandleRefPtr& aRHS) { return !(aLHS == aRHS); } } // namespace mozilla #endif // mozilla_HandleRefPtr_h