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 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 
7 #ifndef CORE_FXCRT_CFX_WEAK_PTR_H_
8 #define CORE_FXCRT_CFX_WEAK_PTR_H_
9 
10 #include <cstddef>
11 #include <memory>
12 #include <utility>
13 
14 #include "core/fxcrt/cfx_retain_ptr.h"
15 #include "core/fxcrt/fx_system.h"
16 
17 template <class T, class D = std::default_delete<T>>
18 class CFX_WeakPtr {
19  public:
CFX_WeakPtr()20   CFX_WeakPtr() {}
CFX_WeakPtr(const CFX_WeakPtr & that)21   CFX_WeakPtr(const CFX_WeakPtr& that) : m_pHandle(that.m_pHandle) {}
CFX_WeakPtr(CFX_WeakPtr && that)22   CFX_WeakPtr(CFX_WeakPtr&& that) { Swap(that); }
CFX_WeakPtr(std::unique_ptr<T,D> pObj)23   explicit CFX_WeakPtr(std::unique_ptr<T, D> pObj)
24       : m_pHandle(new Handle(std::move(pObj))) {}
25 
26   // Deliberately implicit to allow passing nullptr.
27   // NOLINTNEXTLINE(runtime/explicit)
CFX_WeakPtr(std::nullptr_t arg)28   CFX_WeakPtr(std::nullptr_t arg) {}
29 
30   explicit operator bool() const { return m_pHandle && !!m_pHandle->Get(); }
HasOneRef()31   bool HasOneRef() const { return m_pHandle && m_pHandle->HasOneRef(); }
32   T* operator->() { return m_pHandle->Get(); }
33   const T* operator->() const { return m_pHandle->Get(); }
34   CFX_WeakPtr& operator=(const CFX_WeakPtr& that) {
35     m_pHandle = that.m_pHandle;
36     return *this;
37   }
38   bool operator==(const CFX_WeakPtr& that) const {
39     return m_pHandle == that.m_pHandle;
40   }
41   bool operator!=(const CFX_WeakPtr& that) const { return !(*this == that); }
42 
Get()43   T* Get() const { return m_pHandle ? m_pHandle->Get() : nullptr; }
DeleteObject()44   void DeleteObject() {
45     if (m_pHandle) {
46       m_pHandle->Clear();
47       m_pHandle.Reset();
48     }
49   }
Reset()50   void Reset() { m_pHandle.Reset(); }
Reset(std::unique_ptr<T,D> pObj)51   void Reset(std::unique_ptr<T, D> pObj) {
52     m_pHandle.Reset(new Handle(std::move(pObj)));
53   }
Swap(CFX_WeakPtr & that)54   void Swap(CFX_WeakPtr& that) { m_pHandle.Swap(that.m_pHandle); }
55 
56  private:
57   class Handle {
58    public:
Handle(std::unique_ptr<T,D> ptr)59     explicit Handle(std::unique_ptr<T, D> ptr)
60         : m_nCount(0), m_pObj(std::move(ptr)) {}
Reset(std::unique_ptr<T,D> ptr)61     void Reset(std::unique_ptr<T, D> ptr) { m_pObj = std::move(ptr); }
Clear()62     void Clear() {     // Now you're all weak ptrs ...
63       m_pObj.reset();  // unique_ptr nulls first before invoking delete.
64     }
Get()65     T* Get() const { return m_pObj.get(); }
Retain()66     T* Retain() {
67       ++m_nCount;
68       return m_pObj.get();
69     }
Release()70     void Release() {
71       if (--m_nCount == 0)
72         delete this;
73     }
HasOneRef()74     bool HasOneRef() const { return m_nCount == 1; }
75 
76    private:
~Handle()77     ~Handle() {}
78 
79     intptr_t m_nCount;
80     std::unique_ptr<T, D> m_pObj;
81   };
82 
83   CFX_RetainPtr<Handle> m_pHandle;
84 };
85 
86 #endif  // CORE_FXCRT_CFX_WEAK_PTR_H_
87