• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 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_UNOWNED_PTR_H_
6 #define CORE_FXCRT_UNOWNED_PTR_H_
7 
8 #include <functional>
9 #include <memory>
10 #include <type_traits>
11 #include <utility>
12 
13 // UnownedPtr is a smart pointer class that behaves very much like a
14 // standard C-style pointer. The advantages of using it over raw
15 // pointers are:
16 //
17 // 1. It documents the nature of the pointer with no need to add a comment
18 //    explaining that is it // Not owned. Additionally, an attempt to delete
19 //    an unowned ptr will fail to compile rather than silently succeeding,
20 //    since it is a class and not a raw pointer.
21 //
22 // 2. When built for a memory tool like ASAN, the class provides a destructor
23 //    which checks that the object being pointed to is still alive.
24 //
25 // Hence, when using UnownedPtr, no dangling pointers are ever permitted,
26 // even if they are not de-referenced after becoming dangling. The style of
27 // programming required is that the lifetime an object containing an
28 // UnownedPtr must be strictly less than the object to which it points.
29 //
30 // The same checks are also performed at assignment time to prove that the
31 // old value was not a dangling pointer, either.
32 //
33 // The array indexing operation [] is not supported on an unowned ptr,
34 // because an unowned ptr expresses a one to one relationship with some
35 // other heap object.
36 
37 namespace fxcrt {
38 
39 template <class T>
40 class UnownedPtr {
41  public:
42   UnownedPtr() = default;
UnownedPtr(const UnownedPtr & that)43   UnownedPtr(const UnownedPtr& that) : UnownedPtr(that.Get()) {}
44 
45   template <typename U>
UnownedPtr(U * pObj)46   explicit UnownedPtr(U* pObj) : m_pObj(pObj) {}
47 
48   // Deliberately implicit to allow returning nullptrs.
49   // NOLINTNEXTLINE(runtime/explicit)
UnownedPtr(std::nullptr_t ptr)50   UnownedPtr(std::nullptr_t ptr) {}
51 
~UnownedPtr()52   ~UnownedPtr() { ProbeForLowSeverityLifetimeIssue(); }
53 
54   UnownedPtr& operator=(T* that) {
55     ProbeForLowSeverityLifetimeIssue();
56     m_pObj = that;
57     return *this;
58   }
59 
60   UnownedPtr& operator=(const UnownedPtr& that) {
61     ProbeForLowSeverityLifetimeIssue();
62     if (*this != that)
63       m_pObj = that.Get();
64     return *this;
65   }
66 
67   bool operator==(const UnownedPtr& that) const { return Get() == that.Get(); }
68   bool operator!=(const UnownedPtr& that) const { return !(*this == that); }
69   bool operator<(const UnownedPtr& that) const {
70     return std::less<T*>()(Get(), that.Get());
71   }
72 
73   template <typename U>
74   bool operator==(const U* that) const {
75     return Get() == that;
76   }
77 
78   template <typename U>
79   bool operator!=(const U* that) const {
80     return !(*this == that);
81   }
82 
Get()83   T* Get() const { return m_pObj; }
84 
Release()85   T* Release() {
86     ProbeForLowSeverityLifetimeIssue();
87     T* pTemp = nullptr;
88     std::swap(pTemp, m_pObj);
89     return pTemp;
90   }
91 
92   explicit operator bool() const { return !!m_pObj; }
93   T& operator*() const { return *m_pObj; }
94   T* operator->() const { return m_pObj; }
95 
96  private:
ProbeForLowSeverityLifetimeIssue()97   inline void ProbeForLowSeverityLifetimeIssue() {
98 #if defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
99     if (m_pObj)
100       reinterpret_cast<const volatile uint8_t*>(m_pObj)[0];
101 #endif
102   }
103 
104   T* m_pObj = nullptr;
105 };
106 
107 template <typename T, typename U>
108 inline bool operator==(const U* lhs, const UnownedPtr<T>& rhs) {
109   return rhs == lhs;
110 }
111 
112 template <typename T, typename U>
113 inline bool operator!=(const U* lhs, const UnownedPtr<T>& rhs) {
114   return rhs != lhs;
115 }
116 
117 }  // namespace fxcrt
118 
119 using fxcrt::UnownedPtr;
120 
121 #endif  // CORE_FXCRT_UNOWNED_PTR_H_
122