1 // Copyright 2017 The Chromium 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 BASE_MEMORY_SCOPED_REFPTR_H_ 6 #define BASE_MEMORY_SCOPED_REFPTR_H_ 7 8 #include <stddef.h> 9 10 #include <iosfwd> 11 #include <type_traits> 12 #include <utility> 13 14 #include "base/compiler_specific.h" 15 #include "base/logging.h" 16 #include "base/macros.h" 17 18 template <class T> 19 class scoped_refptr; 20 21 namespace base { 22 23 template <class, typename> 24 class RefCounted; 25 template <class, typename> 26 class RefCountedThreadSafe; 27 28 template <typename T> 29 scoped_refptr<T> AdoptRef(T* t); 30 31 namespace subtle { 32 33 enum AdoptRefTag { kAdoptRefTag }; 34 enum StartRefCountFromZeroTag { kStartRefCountFromZeroTag }; 35 enum StartRefCountFromOneTag { kStartRefCountFromOneTag }; 36 37 template <typename T, typename U, typename V> 38 constexpr bool IsRefCountPreferenceOverridden(const T*, 39 const RefCounted<U, V>*) { 40 return !std::is_same<std::decay_t<decltype(T::kRefCountPreference)>, 41 std::decay_t<decltype(U::kRefCountPreference)>>::value; 42 } 43 44 template <typename T, typename U, typename V> 45 constexpr bool IsRefCountPreferenceOverridden( 46 const T*, 47 const RefCountedThreadSafe<U, V>*) { 48 return !std::is_same<std::decay_t<decltype(T::kRefCountPreference)>, 49 std::decay_t<decltype(U::kRefCountPreference)>>::value; 50 } 51 52 constexpr bool IsRefCountPreferenceOverridden(...) { 53 return false; 54 } 55 56 } // namespace subtle 57 58 // Creates a scoped_refptr from a raw pointer without incrementing the reference 59 // count. Use this only for a newly created object whose reference count starts 60 // from 1 instead of 0. 61 template <typename T> 62 scoped_refptr<T> AdoptRef(T* obj) { 63 using Tag = std::decay_t<decltype(T::kRefCountPreference)>; 64 static_assert(std::is_same<subtle::StartRefCountFromOneTag, Tag>::value, 65 "Use AdoptRef only for the reference count starts from one."); 66 67 DCHECK(obj); 68 DCHECK(obj->HasOneRef()); 69 obj->Adopted(); 70 return scoped_refptr<T>(obj, subtle::kAdoptRefTag); 71 } 72 73 namespace subtle { 74 75 template <typename T> 76 scoped_refptr<T> AdoptRefIfNeeded(T* obj, StartRefCountFromZeroTag) { 77 return scoped_refptr<T>(obj); 78 } 79 80 template <typename T> 81 scoped_refptr<T> AdoptRefIfNeeded(T* obj, StartRefCountFromOneTag) { 82 return AdoptRef(obj); 83 } 84 85 } // namespace subtle 86 87 // Constructs an instance of T, which is a ref counted type, and wraps the 88 // object into a scoped_refptr<T>. 89 template <typename T, typename... Args> 90 scoped_refptr<T> MakeRefCounted(Args&&... args) { 91 T* obj = new T(std::forward<Args>(args)...); 92 return subtle::AdoptRefIfNeeded(obj, T::kRefCountPreference); 93 } 94 95 // Takes an instance of T, which is a ref counted type, and wraps the object 96 // into a scoped_refptr<T>. 97 template <typename T> 98 scoped_refptr<T> WrapRefCounted(T* t) { 99 return scoped_refptr<T>(t); 100 } 101 102 } // namespace base 103 104 // 105 // A smart pointer class for reference counted objects. Use this class instead 106 // of calling AddRef and Release manually on a reference counted object to 107 // avoid common memory leaks caused by forgetting to Release an object 108 // reference. Sample usage: 109 // 110 // class MyFoo : public RefCounted<MyFoo> { 111 // ... 112 // private: 113 // friend class RefCounted<MyFoo>; // Allow destruction by RefCounted<>. 114 // ~MyFoo(); // Destructor must be private/protected. 115 // }; 116 // 117 // void some_function() { 118 // scoped_refptr<MyFoo> foo = MakeRefCounted<MyFoo>(); 119 // foo->Method(param); 120 // // |foo| is released when this function returns 121 // } 122 // 123 // void some_other_function() { 124 // scoped_refptr<MyFoo> foo = MakeRefCounted<MyFoo>(); 125 // ... 126 // foo.reset(); // explicitly releases |foo| 127 // ... 128 // if (foo) 129 // foo->Method(param); 130 // } 131 // 132 // The above examples show how scoped_refptr<T> acts like a pointer to T. 133 // Given two scoped_refptr<T> classes, it is also possible to exchange 134 // references between the two objects, like so: 135 // 136 // { 137 // scoped_refptr<MyFoo> a = MakeRefCounted<MyFoo>(); 138 // scoped_refptr<MyFoo> b; 139 // 140 // b.swap(a); 141 // // now, |b| references the MyFoo object, and |a| references nullptr. 142 // } 143 // 144 // To make both |a| and |b| in the above example reference the same MyFoo 145 // object, simply use the assignment operator: 146 // 147 // { 148 // scoped_refptr<MyFoo> a = MakeRefCounted<MyFoo>(); 149 // scoped_refptr<MyFoo> b; 150 // 151 // b = a; 152 // // now, |a| and |b| each own a reference to the same MyFoo object. 153 // } 154 // 155 // Also see Chromium's ownership and calling conventions: 156 // https://chromium.googlesource.com/chromium/src/+/lkgr/styleguide/c++/c++.md#object-ownership-and-calling-conventions 157 // Specifically: 158 // If the function (at least sometimes) takes a ref on a refcounted object, 159 // declare the param as scoped_refptr<T>. The caller can decide whether it 160 // wishes to transfer ownership (by calling std::move(t) when passing t) or 161 // retain its ref (by simply passing t directly). 162 // In other words, use scoped_refptr like you would a std::unique_ptr except 163 // in the odd case where it's required to hold on to a ref while handing one 164 // to another component (if a component merely needs to use t on the stack 165 // without keeping a ref: pass t as a raw T*). 166 template <class T> 167 class scoped_refptr { 168 public: 169 typedef T element_type; 170 171 constexpr scoped_refptr() = default; 172 173 // Constructs from raw pointer. constexpr if |p| is null. 174 constexpr scoped_refptr(T* p) : ptr_(p) { 175 if (ptr_) 176 AddRef(ptr_); 177 } 178 179 // Copy constructor. This is required in addition to the copy conversion 180 // constructor below. 181 scoped_refptr(const scoped_refptr& r) : scoped_refptr(r.ptr_) {} 182 183 // Copy conversion constructor. 184 template <typename U, 185 typename = typename std::enable_if< 186 std::is_convertible<U*, T*>::value>::type> 187 scoped_refptr(const scoped_refptr<U>& r) : scoped_refptr(r.ptr_) {} 188 189 // Move constructor. This is required in addition to the move conversion 190 // constructor below. 191 scoped_refptr(scoped_refptr&& r) noexcept : ptr_(r.ptr_) { r.ptr_ = nullptr; } 192 193 // Move conversion constructor. 194 template <typename U, 195 typename = typename std::enable_if< 196 std::is_convertible<U*, T*>::value>::type> 197 scoped_refptr(scoped_refptr<U>&& r) noexcept : ptr_(r.ptr_) { 198 r.ptr_ = nullptr; 199 } 200 201 ~scoped_refptr() { 202 static_assert(!base::subtle::IsRefCountPreferenceOverridden( 203 static_cast<T*>(nullptr), static_cast<T*>(nullptr)), 204 "It's unsafe to override the ref count preference." 205 " Please remove REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE" 206 " from subclasses."); 207 if (ptr_) 208 Release(ptr_); 209 } 210 211 T* get() const { return ptr_; } 212 213 T& operator*() const { 214 DCHECK(ptr_); 215 return *ptr_; 216 } 217 218 T* operator->() const { 219 DCHECK(ptr_); 220 return ptr_; 221 } 222 223 scoped_refptr& operator=(T* p) { return *this = scoped_refptr(p); } 224 225 // Unified assignment operator. 226 scoped_refptr& operator=(scoped_refptr r) noexcept { 227 swap(r); 228 return *this; 229 } 230 231 // Sets managed object to null and releases reference to the previous managed 232 // object, if it existed. 233 void reset() { scoped_refptr().swap(*this); } 234 235 void swap(scoped_refptr& r) noexcept { std::swap(ptr_, r.ptr_); } 236 237 explicit operator bool() const { return ptr_ != nullptr; } 238 239 template <typename U> 240 bool operator==(const scoped_refptr<U>& rhs) const { 241 return ptr_ == rhs.get(); 242 } 243 244 template <typename U> 245 bool operator!=(const scoped_refptr<U>& rhs) const { 246 return !operator==(rhs); 247 } 248 249 template <typename U> 250 bool operator<(const scoped_refptr<U>& rhs) const { 251 return ptr_ < rhs.get(); 252 } 253 254 protected: 255 T* ptr_ = nullptr; 256 257 private: 258 template <typename U> 259 friend scoped_refptr<U> base::AdoptRef(U*); 260 261 scoped_refptr(T* p, base::subtle::AdoptRefTag) : ptr_(p) {} 262 263 // Friend required for move constructors that set r.ptr_ to null. 264 template <typename U> 265 friend class scoped_refptr; 266 267 // Non-inline helpers to allow: 268 // class Opaque; 269 // extern template class scoped_refptr<Opaque>; 270 // Otherwise the compiler will complain that Opaque is an incomplete type. 271 static void AddRef(T* ptr); 272 static void Release(T* ptr); 273 }; 274 275 // static 276 template <typename T> 277 void scoped_refptr<T>::AddRef(T* ptr) { 278 ptr->AddRef(); 279 } 280 281 // static 282 template <typename T> 283 void scoped_refptr<T>::Release(T* ptr) { 284 ptr->Release(); 285 } 286 287 template <typename T, typename U> 288 bool operator==(const scoped_refptr<T>& lhs, const U* rhs) { 289 return lhs.get() == rhs; 290 } 291 292 template <typename T, typename U> 293 bool operator==(const T* lhs, const scoped_refptr<U>& rhs) { 294 return lhs == rhs.get(); 295 } 296 297 template <typename T> 298 bool operator==(const scoped_refptr<T>& lhs, std::nullptr_t null) { 299 return !static_cast<bool>(lhs); 300 } 301 302 template <typename T> 303 bool operator==(std::nullptr_t null, const scoped_refptr<T>& rhs) { 304 return !static_cast<bool>(rhs); 305 } 306 307 template <typename T, typename U> 308 bool operator!=(const scoped_refptr<T>& lhs, const U* rhs) { 309 return !operator==(lhs, rhs); 310 } 311 312 template <typename T, typename U> 313 bool operator!=(const T* lhs, const scoped_refptr<U>& rhs) { 314 return !operator==(lhs, rhs); 315 } 316 317 template <typename T> 318 bool operator!=(const scoped_refptr<T>& lhs, std::nullptr_t null) { 319 return !operator==(lhs, null); 320 } 321 322 template <typename T> 323 bool operator!=(std::nullptr_t null, const scoped_refptr<T>& rhs) { 324 return !operator==(null, rhs); 325 } 326 327 template <typename T> 328 std::ostream& operator<<(std::ostream& out, const scoped_refptr<T>& p) { 329 return out << p.get(); 330 } 331 332 template <typename T> 333 void swap(scoped_refptr<T>& lhs, scoped_refptr<T>& rhs) noexcept { 334 lhs.swap(rhs); 335 } 336 337 #endif // BASE_MEMORY_SCOPED_REFPTR_H_ 338