| // Copyright 2016 The PDFium Authors | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #ifndef CORE_FXCRT_RETAIN_PTR_H_ | 
 | #define CORE_FXCRT_RETAIN_PTR_H_ | 
 |  | 
 | #include <stdint.h> | 
 |  | 
 | #include <functional> | 
 | #include <memory> | 
 | #include <type_traits> | 
 | #include <utility> | 
 |  | 
 | #include "core/fxcrt/unowned_ptr.h" | 
 | #include "third_party/base/check.h" | 
 | #include "third_party/base/compiler_specific.h" | 
 |  | 
 | namespace fxcrt { | 
 |  | 
 | // Used with std::unique_ptr to Release() objects that can't be deleted. | 
 | template <class T> | 
 | struct ReleaseDeleter { | 
 |   inline void operator()(T* ptr) const { ptr->Release(); } | 
 | }; | 
 |  | 
 | // Analogous to base's scoped_refptr. | 
 | template <class T> | 
 | class TRIVIAL_ABI RetainPtr { | 
 |  public: | 
 |   RetainPtr() noexcept = default; | 
 |  | 
 |   // Deliberately implicit to allow returning nullptrs. | 
 |   // NOLINTNEXTLINE(runtime/explicit) | 
 |   RetainPtr(std::nullptr_t ptr) {} | 
 |  | 
 |   explicit RetainPtr(T* pObj) noexcept : m_pObj(pObj) { | 
 |     if (m_pObj) | 
 |       m_pObj->Retain(); | 
 |   } | 
 |  | 
 |   // Copy-construct a RetainPtr. | 
 |   // Required in addition to copy conversion constructor below. | 
 |   RetainPtr(const RetainPtr& that) noexcept : RetainPtr(that.Get()) {} | 
 |  | 
 |   // Move-construct a RetainPtr. After construction, |that| will be NULL. | 
 |   // Required in addition to move conversion constructor below. | 
 |   RetainPtr(RetainPtr&& that) noexcept { Unleak(that.Leak()); } | 
 |  | 
 |   // Copy conversion constructor. | 
 |   template <class U, | 
 |             typename = typename std::enable_if< | 
 |                 std::is_convertible<U*, T*>::value>::type> | 
 |   RetainPtr(const RetainPtr<U>& that) : RetainPtr(that.Get()) {} | 
 |  | 
 |   // Move-conversion constructor. | 
 |   template <class U, | 
 |             typename = typename std::enable_if< | 
 |                 std::is_convertible<U*, T*>::value>::type> | 
 |   RetainPtr(RetainPtr<U>&& that) noexcept { | 
 |     Unleak(that.Leak()); | 
 |   } | 
 |  | 
 |   // Assign a RetainPtr from nullptr; | 
 |   RetainPtr& operator=(std::nullptr_t) noexcept { | 
 |     Reset(); | 
 |     return *this; | 
 |   } | 
 |  | 
 |   // Copy-assign a RetainPtr. | 
 |   // Required in addition to copy conversion assignment below. | 
 |   RetainPtr& operator=(const RetainPtr& that) { | 
 |     if (*this != that) | 
 |       Reset(that.Get()); | 
 |     return *this; | 
 |   } | 
 |  | 
 |   // Move-assign a RetainPtr. After assignment, |that| will be NULL. | 
 |   // Required in addition to move conversion assignment below. | 
 |   RetainPtr& operator=(RetainPtr&& that) noexcept { | 
 |     Unleak(that.Leak()); | 
 |     return *this; | 
 |   } | 
 |  | 
 |   // Copy-convert assign a RetainPtr. | 
 |   template <class U, | 
 |             typename = typename std::enable_if< | 
 |                 std::is_convertible<U*, T*>::value>::type> | 
 |   RetainPtr& operator=(const RetainPtr<U>& that) { | 
 |     if (*this != that) | 
 |       Reset(that.Get()); | 
 |     return *this; | 
 |   } | 
 |  | 
 |   // Move-convert assign a RetainPtr. After assignment, |that| will be NULL. | 
 |   template <class U, | 
 |             typename = typename std::enable_if< | 
 |                 std::is_convertible<U*, T*>::value>::type> | 
 |   RetainPtr& operator=(RetainPtr<U>&& that) noexcept { | 
 |     Unleak(that.Leak()); | 
 |     return *this; | 
 |   } | 
 |  | 
 |   ~RetainPtr() = default; | 
 |  | 
 |   template <class U> | 
 |   U* AsRaw() const { | 
 |     return static_cast<U*>(Get()); | 
 |   } | 
 |  | 
 |   template <class U> | 
 |   RetainPtr<U> As() const { | 
 |     return RetainPtr<U>(AsRaw<U>()); | 
 |   } | 
 |  | 
 |   void Reset(T* obj = nullptr) { | 
 |     if (obj) | 
 |       obj->Retain(); | 
 |     m_pObj.reset(obj); | 
 |   } | 
 |  | 
 |   operator T*() const noexcept { return Get(); } | 
 |   T* Get() const noexcept { return m_pObj.get(); } | 
 |  | 
 |   UnownedPtr<T> BackPointer() const { return UnownedPtr<T>(Get()); } | 
 |   void Swap(RetainPtr& that) { m_pObj.swap(that.m_pObj); } | 
 |  | 
 |   // Useful for passing notion of object ownership across a C API. | 
 |   T* Leak() { return m_pObj.release(); } | 
 |   void Unleak(T* ptr) { m_pObj.reset(ptr); } | 
 |  | 
 |   bool operator==(const RetainPtr& that) const { return Get() == that.Get(); } | 
 |   bool operator!=(const RetainPtr& that) const { return !(*this == that); } | 
 |  | 
 |   template <typename U> | 
 |   bool operator==(const U& that) const { | 
 |     return Get() == that; | 
 |   } | 
 |  | 
 |   template <typename U> | 
 |   bool operator!=(const U& that) const { | 
 |     return !(*this == that); | 
 |   } | 
 |  | 
 |   bool operator<(const RetainPtr& that) const { | 
 |     return std::less<T*>()(Get(), that.Get()); | 
 |   } | 
 |  | 
 |   explicit operator bool() const { return !!m_pObj; } | 
 |   T& operator*() const { return *m_pObj; } | 
 |   T* operator->() const { return m_pObj.get(); } | 
 |  | 
 |  private: | 
 |   std::unique_ptr<T, ReleaseDeleter<T>> m_pObj; | 
 | }; | 
 |  | 
 | // Trivial implementation - internal ref count with virtual destructor. | 
 | class Retainable { | 
 |  public: | 
 |   Retainable() = default; | 
 |  | 
 |   bool HasOneRef() const { return m_nRefCount == 1; } | 
 |  | 
 |  protected: | 
 |   virtual ~Retainable() = default; | 
 |  | 
 |  private: | 
 |   template <typename U> | 
 |   friend struct ReleaseDeleter; | 
 |  | 
 |   template <typename U> | 
 |   friend class RetainPtr; | 
 |  | 
 |   Retainable(const Retainable& that) = delete; | 
 |   Retainable& operator=(const Retainable& that) = delete; | 
 |  | 
 |   // These need to be const methods operating on a mutable member so that | 
 |   // RetainPtr<const T> can be used for an object that is otherwise const | 
 |   // apart from the internal ref-counting. | 
 |   void Retain() const { | 
 |     ++m_nRefCount; | 
 |     CHECK(m_nRefCount > 0); | 
 |   } | 
 |   void Release() const { | 
 |     CHECK(m_nRefCount > 0); | 
 |     if (--m_nRefCount == 0) | 
 |       delete this; | 
 |   } | 
 |  | 
 |   mutable uintptr_t m_nRefCount = 0; | 
 |   static_assert(std::is_unsigned<decltype(m_nRefCount)>::value, | 
 |                 "m_nRefCount must be an unsigned type for overflow check" | 
 |                 "to work properly in Retain()"); | 
 | }; | 
 |  | 
 | }  // namespace fxcrt | 
 |  | 
 | using fxcrt::ReleaseDeleter; | 
 | using fxcrt::Retainable; | 
 | using fxcrt::RetainPtr; | 
 |  | 
 | namespace pdfium { | 
 |  | 
 | // Helper to make a RetainPtr along the lines of std::make_unique<>(). | 
 | // Arguments are forwarded to T's constructor. Classes managed by RetainPtr | 
 | // should have protected (or private) constructors, and should friend this | 
 | // function. | 
 | template <typename T, typename... Args> | 
 | RetainPtr<T> MakeRetain(Args&&... args) { | 
 |   return RetainPtr<T>(new T(std::forward<Args>(args)...)); | 
 | } | 
 |  | 
 | // Type-deducing wrapper to make a RetainPtr from an ordinary pointer, | 
 | // since equivalent constructor is explicit. | 
 | template <typename T> | 
 | RetainPtr<T> WrapRetain(T* that) { | 
 |   return RetainPtr<T>(that); | 
 | } | 
 |  | 
 | }  // namespace pdfium | 
 |  | 
 | // Macro to allow construction via MakeRetain<>() only, when used | 
 | // with a private constructor in a class. | 
 | #define CONSTRUCT_VIA_MAKE_RETAIN         \ | 
 |   template <typename T, typename... Args> \ | 
 |   friend RetainPtr<T> pdfium::MakeRetain(Args&&... args) | 
 |  | 
 | #endif  // CORE_FXCRT_RETAIN_PTR_H_ |