• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef CORE_FXCRT_RETAIN_PTR_H_
6 #define CORE_FXCRT_RETAIN_PTR_H_
7 
8 #include <functional>
9 #include <memory>
10 #include <utility>
11 
12 #include "core/fxcrt/fx_system.h"
13 
14 namespace fxcrt {
15 
16 // Used with std::unique_ptr to Release() objects that can't be deleted.
17 template <class T>
18 struct ReleaseDeleter {
operatorReleaseDeleter19   inline void operator()(T* ptr) const { ptr->Release(); }
20 };
21 
22 // Analogous to base's scoped_refptr.
23 template <class T>
24 class RetainPtr {
25  public:
RetainPtr(T * pObj)26   explicit RetainPtr(T* pObj) : m_pObj(pObj) {
27     if (m_pObj)
28       m_pObj->Retain();
29   }
30 
31   RetainPtr() = default;
RetainPtr(const RetainPtr & that)32   RetainPtr(const RetainPtr& that) : RetainPtr(that.Get()) {}
RetainPtr(RetainPtr && that)33   RetainPtr(RetainPtr&& that) noexcept { Swap(that); }
34 
35   // Deliberately implicit to allow returning nullptrs.
36   // NOLINTNEXTLINE(runtime/explicit)
RetainPtr(std::nullptr_t ptr)37   RetainPtr(std::nullptr_t ptr) {}
38 
39   template <class U>
RetainPtr(const RetainPtr<U> & that)40   RetainPtr(const RetainPtr<U>& that) : RetainPtr(that.Get()) {}
41 
42   template <class U>
As()43   RetainPtr<U> As() const {
44     return RetainPtr<U>(static_cast<U*>(Get()));
45   }
46 
47   void Reset(T* obj = nullptr) {
48     if (obj)
49       obj->Retain();
50     m_pObj.reset(obj);
51   }
52 
Get()53   T* Get() const { return m_pObj.get(); }
Swap(RetainPtr & that)54   void Swap(RetainPtr& that) { m_pObj.swap(that.m_pObj); }
55 
56   // Useful for passing notion of object ownership across a C API.
Leak()57   T* Leak() { return m_pObj.release(); }
Unleak(T * ptr)58   void Unleak(T* ptr) { m_pObj.reset(ptr); }
59 
60   RetainPtr& operator=(const RetainPtr& that) {
61     if (*this != that)
62       Reset(that.Get());
63     return *this;
64   }
65 
66   RetainPtr& operator=(RetainPtr&& that) {
67     m_pObj.reset(that.Leak());
68     return *this;
69   }
70 
71   bool operator==(const RetainPtr& that) const { return Get() == that.Get(); }
72   bool operator!=(const RetainPtr& that) const { return !(*this == that); }
73 
74   bool operator<(const RetainPtr& that) const {
75     return std::less<T*>()(Get(), that.Get());
76   }
77 
78   explicit operator bool() const { return !!m_pObj; }
79   T& operator*() const { return *m_pObj.get(); }
80   T* operator->() const { return m_pObj.get(); }
81 
82  private:
83   std::unique_ptr<T, ReleaseDeleter<T>> m_pObj;
84 };
85 
86 // Trivial implementation - internal ref count with virtual destructor.
87 class Retainable {
88  public:
HasOneRef()89   bool HasOneRef() const { return m_nRefCount == 1; }
90 
91  protected:
92   virtual ~Retainable() = default;
93 
94  private:
95   template <typename U>
96   friend struct ReleaseDeleter;
97 
98   template <typename U>
99   friend class RetainPtr;
100 
Retain()101   void Retain() { ++m_nRefCount; }
Release()102   void Release() {
103     ASSERT(m_nRefCount > 0);
104     if (--m_nRefCount == 0)
105       delete this;
106   }
107 
108   intptr_t m_nRefCount = 0;
109 };
110 
111 }  // namespace fxcrt
112 
113 using fxcrt::ReleaseDeleter;
114 using fxcrt::RetainPtr;
115 using fxcrt::Retainable;
116 
117 namespace pdfium {
118 
119 // Helper to make a RetainPtr along the lines of std::make_unique<>(),
120 // or pdfium::MakeUnique<>(). Arguments are forwarded to T's constructor.
121 // Classes managed by RetainPtr should have protected (or private)
122 // constructors, and should friend this function.
123 template <typename T, typename... Args>
MakeRetain(Args &&...args)124 RetainPtr<T> MakeRetain(Args&&... args) {
125   return RetainPtr<T>(new T(std::forward<Args>(args)...));
126 }
127 
128 }  // namespace pdfium
129 
130 #endif  // CORE_FXCRT_RETAIN_PTR_H_
131