Home | History | Annotate | Download | only in fxcrt
      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