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_CFX_RETAIN_PTR_H_ 6 #define CORE_FXCRT_CFX_RETAIN_PTR_H_ 7 8 #include <functional> 9 #include <memory> 10 #include <utility> 11 12 #include "core/fxcrt/fx_memory.h" 13 14 // Analogous to base's scoped_refptr. 15 template <class T> 16 class CFX_RetainPtr { 17 public: 18 explicit CFX_RetainPtr(T* pObj) : m_pObj(pObj) { 19 if (m_pObj) 20 m_pObj->Retain(); 21 } 22 23 CFX_RetainPtr() {} 24 CFX_RetainPtr(const CFX_RetainPtr& that) : CFX_RetainPtr(that.Get()) {} 25 CFX_RetainPtr(CFX_RetainPtr&& that) { Swap(that); } 26 27 // Deliberately implicit to allow returning nullptrs. 28 CFX_RetainPtr(std::nullptr_t ptr) {} 29 30 template <class U> 31 CFX_RetainPtr(const CFX_RetainPtr<U>& that) : CFX_RetainPtr(that.Get()) {} 32 33 template <class U> 34 CFX_RetainPtr<U> As() const { 35 return CFX_RetainPtr<U>(static_cast<U*>(Get())); 36 } 37 38 void Reset(T* obj = nullptr) { 39 if (obj) 40 obj->Retain(); 41 m_pObj.reset(obj); 42 } 43 44 T* Get() const { return m_pObj.get(); } 45 void Swap(CFX_RetainPtr& that) { m_pObj.swap(that.m_pObj); } 46 47 // TODO(tsepez): temporary scaffolding, to be removed. 48 T* Leak() { return m_pObj.release(); } 49 void Unleak(T* ptr) { m_pObj.reset(ptr); } 50 51 CFX_RetainPtr& operator=(const CFX_RetainPtr& that) { 52 if (*this != that) 53 Reset(that.Get()); 54 return *this; 55 } 56 57 bool operator==(const CFX_RetainPtr& that) const { 58 return Get() == that.Get(); 59 } 60 bool operator!=(const CFX_RetainPtr& that) const { return !(*this == that); } 61 62 bool operator<(const CFX_RetainPtr& that) const { 63 return std::less<T*>()(Get(), that.Get()); 64 } 65 66 explicit operator bool() const { return !!m_pObj; } 67 T& operator*() const { return *m_pObj.get(); } 68 T* operator->() const { return m_pObj.get(); } 69 70 private: 71 std::unique_ptr<T, ReleaseDeleter<T>> m_pObj; 72 }; 73 74 // Trivial implementation - internal ref count with virtual destructor. 75 class CFX_Retainable { 76 public: 77 bool HasOneRef() const { return m_nRefCount == 1; } 78 79 protected: 80 virtual ~CFX_Retainable() {} 81 82 private: 83 template <typename U> 84 friend struct ReleaseDeleter; 85 86 template <typename U> 87 friend class CFX_RetainPtr; 88 89 void Retain() { ++m_nRefCount; } 90 void Release() { 91 ASSERT(m_nRefCount > 0); 92 if (--m_nRefCount == 0) 93 delete this; 94 } 95 96 intptr_t m_nRefCount = 0; 97 }; 98 99 namespace pdfium { 100 101 // Helper to make a CFX_RetainPtr along the lines of std::make_unique<>(), 102 // or pdfium::MakeUnique<>(). Arguments are forwarded to T's constructor. 103 // Classes managed by CFX_RetainPtr should have protected (or private) 104 // constructors, and should friend this function. 105 template <typename T, typename... Args> 106 CFX_RetainPtr<T> MakeRetain(Args&&... args) { 107 return CFX_RetainPtr<T>(new T(std::forward<Args>(args)...)); 108 } 109 110 } // namespace pdfium 111 112 #endif // CORE_FXCRT_CFX_RETAIN_PTR_H_ 113