1 // Copyright 2017 The Chromium Authors 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/check.h" 15 #include "base/compiler_specific.h" 16 #include "base/memory/raw_ptr_exclusion.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 template <class> 28 class RefCountedDeleteOnSequence; 29 class SequencedTaskRunner; 30 31 template <typename T> 32 scoped_refptr<T> AdoptRef(T* t); 33 34 namespace subtle { 35 36 enum AdoptRefTag { kAdoptRefTag }; 37 enum StartRefCountFromZeroTag { kStartRefCountFromZeroTag }; 38 enum StartRefCountFromOneTag { kStartRefCountFromOneTag }; 39 40 template <typename TagType> 41 struct RefCountPreferenceTagTraits; 42 43 template <> 44 struct RefCountPreferenceTagTraits<StartRefCountFromZeroTag> { 45 static constexpr StartRefCountFromZeroTag kTag = kStartRefCountFromZeroTag; 46 }; 47 48 template <> 49 struct RefCountPreferenceTagTraits<StartRefCountFromOneTag> { 50 static constexpr StartRefCountFromOneTag kTag = kStartRefCountFromOneTag; 51 }; 52 53 template <typename T, typename Tag = typename T::RefCountPreferenceTag> 54 constexpr Tag GetRefCountPreference() { 55 return RefCountPreferenceTagTraits<Tag>::kTag; 56 } 57 58 // scoped_refptr<T> is typically used with one of several RefCounted<T> base 59 // classes or with custom AddRef and Release methods. These overloads dispatch 60 // on which was used. 61 62 template <typename T, typename U, typename V> 63 constexpr bool IsRefCountPreferenceOverridden(const T*, 64 const RefCounted<U, V>*) { 65 return !std::is_same_v<std::decay_t<decltype(GetRefCountPreference<T>())>, 66 std::decay_t<decltype(GetRefCountPreference<U>())>>; 67 } 68 69 template <typename T, typename U, typename V> 70 constexpr bool IsRefCountPreferenceOverridden( 71 const T*, 72 const RefCountedThreadSafe<U, V>*) { 73 return !std::is_same_v<std::decay_t<decltype(GetRefCountPreference<T>())>, 74 std::decay_t<decltype(GetRefCountPreference<U>())>>; 75 } 76 77 template <typename T, typename U> 78 constexpr bool IsRefCountPreferenceOverridden( 79 const T*, 80 const RefCountedDeleteOnSequence<U>*) { 81 return !std::is_same_v<std::decay_t<decltype(GetRefCountPreference<T>())>, 82 std::decay_t<decltype(GetRefCountPreference<U>())>>; 83 } 84 85 constexpr bool IsRefCountPreferenceOverridden(...) { 86 return false; 87 } 88 89 template <typename T, typename U, typename V> 90 constexpr void AssertRefCountBaseMatches(const T*, const RefCounted<U, V>*) { 91 static_assert(std::is_base_of_v<U, T>, 92 "T implements RefCounted<U>, but U is not a base of T."); 93 } 94 95 template <typename T, typename U, typename V> 96 constexpr void AssertRefCountBaseMatches(const T*, 97 const RefCountedThreadSafe<U, V>*) { 98 static_assert( 99 std::is_base_of_v<U, T>, 100 "T implements RefCountedThreadSafe<U>, but U is not a base of T."); 101 } 102 103 template <typename T, typename U> 104 constexpr void AssertRefCountBaseMatches(const T*, 105 const RefCountedDeleteOnSequence<U>*) { 106 static_assert( 107 std::is_base_of_v<U, T>, 108 "T implements RefCountedDeleteOnSequence<U>, but U is not a base of T."); 109 } 110 111 constexpr void AssertRefCountBaseMatches(...) {} 112 113 } // namespace subtle 114 115 // Creates a scoped_refptr from a raw pointer without incrementing the reference 116 // count. Use this only for a newly created object whose reference count starts 117 // from 1 instead of 0. 118 template <typename T> 119 scoped_refptr<T> AdoptRef(T* obj) { 120 using Tag = std::decay_t<decltype(subtle::GetRefCountPreference<T>())>; 121 static_assert(std::is_same_v<subtle::StartRefCountFromOneTag, Tag>, 122 "Use AdoptRef only if the reference count starts from one."); 123 124 DCHECK(obj); 125 DCHECK(obj->HasOneRef()); 126 obj->Adopted(); 127 return scoped_refptr<T>(obj, subtle::kAdoptRefTag); 128 } 129 130 namespace subtle { 131 132 template <typename T> 133 scoped_refptr<T> AdoptRefIfNeeded(T* obj, StartRefCountFromZeroTag) { 134 return scoped_refptr<T>(obj); 135 } 136 137 template <typename T> 138 scoped_refptr<T> AdoptRefIfNeeded(T* obj, StartRefCountFromOneTag) { 139 return AdoptRef(obj); 140 } 141 142 } // namespace subtle 143 144 // Constructs an instance of T, which is a ref counted type, and wraps the 145 // object into a scoped_refptr<T>. 146 template <typename T, typename... Args> 147 scoped_refptr<T> MakeRefCounted(Args&&... args) { 148 T* obj = new T(std::forward<Args>(args)...); 149 return subtle::AdoptRefIfNeeded(obj, subtle::GetRefCountPreference<T>()); 150 } 151 152 // Takes an instance of T, which is a ref counted type, and wraps the object 153 // into a scoped_refptr<T>. 154 template <typename T> 155 scoped_refptr<T> WrapRefCounted(T* t) { 156 return scoped_refptr<T>(t); 157 } 158 159 } // namespace base 160 161 // 162 // A smart pointer class for reference counted objects. Use this class instead 163 // of calling AddRef and Release manually on a reference counted object to 164 // avoid common memory leaks caused by forgetting to Release an object 165 // reference. Sample usage: 166 // 167 // class MyFoo : public RefCounted<MyFoo> { 168 // ... 169 // private: 170 // friend class RefCounted<MyFoo>; // Allow destruction by RefCounted<>. 171 // ~MyFoo(); // Destructor must be private/protected. 172 // }; 173 // 174 // void some_function() { 175 // scoped_refptr<MyFoo> foo = MakeRefCounted<MyFoo>(); 176 // foo->Method(param); 177 // // |foo| is released when this function returns 178 // } 179 // 180 // void some_other_function() { 181 // scoped_refptr<MyFoo> foo = MakeRefCounted<MyFoo>(); 182 // ... 183 // foo.reset(); // explicitly releases |foo| 184 // ... 185 // if (foo) 186 // foo->Method(param); 187 // } 188 // 189 // The above examples show how scoped_refptr<T> acts like a pointer to T. 190 // Given two scoped_refptr<T> classes, it is also possible to exchange 191 // references between the two objects, like so: 192 // 193 // { 194 // scoped_refptr<MyFoo> a = MakeRefCounted<MyFoo>(); 195 // scoped_refptr<MyFoo> b; 196 // 197 // b.swap(a); 198 // // now, |b| references the MyFoo object, and |a| references nullptr. 199 // } 200 // 201 // To make both |a| and |b| in the above example reference the same MyFoo 202 // object, simply use the assignment operator: 203 // 204 // { 205 // scoped_refptr<MyFoo> a = MakeRefCounted<MyFoo>(); 206 // scoped_refptr<MyFoo> b; 207 // 208 // b = a; 209 // // now, |a| and |b| each own a reference to the same MyFoo object. 210 // } 211 // 212 // Also see Chromium's ownership and calling conventions: 213 // https://chromium.googlesource.com/chromium/src/+/lkgr/styleguide/c++/c++.md#object-ownership-and-calling-conventions 214 // Specifically: 215 // If the function (at least sometimes) takes a ref on a refcounted object, 216 // declare the param as scoped_refptr<T>. The caller can decide whether it 217 // wishes to transfer ownership (by calling std::move(t) when passing t) or 218 // retain its ref (by simply passing t directly). 219 // In other words, use scoped_refptr like you would a std::unique_ptr except 220 // in the odd case where it's required to hold on to a ref while handing one 221 // to another component (if a component merely needs to use t on the stack 222 // without keeping a ref: pass t as a raw T*). 223 template <class T> 224 class TRIVIAL_ABI scoped_refptr { 225 public: 226 typedef T element_type; 227 228 constexpr scoped_refptr() = default; 229 230 // Allow implicit construction from nullptr. 231 constexpr scoped_refptr(std::nullptr_t) {} 232 233 // Constructs from a raw pointer. Note that this constructor allows implicit 234 // conversion from T* to scoped_refptr<T> which is strongly discouraged. If 235 // you are creating a new ref-counted object please use 236 // base::MakeRefCounted<T>() or base::WrapRefCounted<T>(). Otherwise you 237 // should move or copy construct from an existing scoped_refptr<T> to the 238 // ref-counted object. 239 scoped_refptr(T* p) : ptr_(p) { 240 if (ptr_) 241 AddRef(ptr_); 242 } 243 244 // Copy constructor. This is required in addition to the copy conversion 245 // constructor below. 246 scoped_refptr(const scoped_refptr& r) : scoped_refptr(r.ptr_) {} 247 248 // Copy conversion constructor. 249 template <typename U, 250 typename = std::enable_if_t<std::is_convertible_v<U*, T*>>> 251 scoped_refptr(const scoped_refptr<U>& r) : scoped_refptr(r.ptr_) {} 252 253 // Move constructor. This is required in addition to the move conversion 254 // constructor below. 255 scoped_refptr(scoped_refptr&& r) noexcept : ptr_(r.ptr_) { r.ptr_ = nullptr; } 256 257 // Move conversion constructor. 258 template <typename U, 259 typename = std::enable_if_t<std::is_convertible_v<U*, T*>>> 260 scoped_refptr(scoped_refptr<U>&& r) noexcept : ptr_(r.ptr_) { 261 r.ptr_ = nullptr; 262 } 263 264 ~scoped_refptr() { 265 static_assert(!base::subtle::IsRefCountPreferenceOverridden( 266 static_cast<T*>(nullptr), static_cast<T*>(nullptr)), 267 "It's unsafe to override the ref count preference." 268 " Please remove REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE" 269 " from subclasses."); 270 if (ptr_) 271 Release(ptr_); 272 } 273 274 T* get() const { return ptr_; } 275 276 T& operator*() const { 277 DCHECK(ptr_); 278 return *ptr_; 279 } 280 281 T* operator->() const { 282 DCHECK(ptr_); 283 return ptr_; 284 } 285 286 scoped_refptr& operator=(std::nullptr_t) { 287 reset(); 288 return *this; 289 } 290 291 scoped_refptr& operator=(T* p) { return *this = scoped_refptr(p); } 292 293 // Unified assignment operator. 294 scoped_refptr& operator=(scoped_refptr r) noexcept { 295 swap(r); 296 return *this; 297 } 298 299 // Sets managed object to null and releases reference to the previous managed 300 // object, if it existed. 301 void reset() { scoped_refptr().swap(*this); } 302 303 // Returns the owned pointer (if any), releasing ownership to the caller. The 304 // caller is responsible for managing the lifetime of the reference. 305 [[nodiscard]] T* release(); 306 307 void swap(scoped_refptr& r) noexcept { std::swap(ptr_, r.ptr_); } 308 309 explicit operator bool() const { return ptr_ != nullptr; } 310 311 template <typename U> 312 bool operator==(const scoped_refptr<U>& rhs) const { 313 return ptr_ == rhs.get(); 314 } 315 316 template <typename U> 317 bool operator!=(const scoped_refptr<U>& rhs) const { 318 return !operator==(rhs); 319 } 320 321 template <typename U> 322 bool operator<(const scoped_refptr<U>& rhs) const { 323 return ptr_ < rhs.get(); 324 } 325 326 protected: 327 // This field is not a raw_ptr<> because it was filtered by the rewriter for: 328 // #union, #addr-of, #global-scope 329 RAW_PTR_EXCLUSION T* ptr_ = nullptr; 330 331 private: 332 template <typename U> 333 friend scoped_refptr<U> base::AdoptRef(U*); 334 friend class ::base::SequencedTaskRunner; 335 336 scoped_refptr(T* p, base::subtle::AdoptRefTag) : ptr_(p) {} 337 338 // Friend required for move constructors that set r.ptr_ to null. 339 template <typename U> 340 friend class scoped_refptr; 341 342 // Non-inline helpers to allow: 343 // class Opaque; 344 // extern template class scoped_refptr<Opaque>; 345 // Otherwise the compiler will complain that Opaque is an incomplete type. 346 static void AddRef(T* ptr); 347 static void Release(T* ptr); 348 }; 349 350 template <typename T> 351 T* scoped_refptr<T>::release() { 352 T* ptr = ptr_; 353 ptr_ = nullptr; 354 return ptr; 355 } 356 357 // static 358 template <typename T> 359 void scoped_refptr<T>::AddRef(T* ptr) { 360 base::subtle::AssertRefCountBaseMatches(ptr, ptr); 361 ptr->AddRef(); 362 } 363 364 // static 365 template <typename T> 366 void scoped_refptr<T>::Release(T* ptr) { 367 base::subtle::AssertRefCountBaseMatches(ptr, ptr); 368 ptr->Release(); 369 } 370 371 template <typename T, typename U> 372 bool operator==(const scoped_refptr<T>& lhs, const U* rhs) { 373 return lhs.get() == rhs; 374 } 375 376 template <typename T, typename U> 377 bool operator==(const T* lhs, const scoped_refptr<U>& rhs) { 378 return lhs == rhs.get(); 379 } 380 381 template <typename T> 382 bool operator==(const scoped_refptr<T>& lhs, std::nullptr_t null) { 383 return !static_cast<bool>(lhs); 384 } 385 386 template <typename T> 387 bool operator==(std::nullptr_t null, const scoped_refptr<T>& rhs) { 388 return !static_cast<bool>(rhs); 389 } 390 391 template <typename T, typename U> 392 bool operator!=(const scoped_refptr<T>& lhs, const U* rhs) { 393 return !operator==(lhs, rhs); 394 } 395 396 template <typename T, typename U> 397 bool operator!=(const T* lhs, const scoped_refptr<U>& rhs) { 398 return !operator==(lhs, rhs); 399 } 400 401 template <typename T> 402 bool operator!=(const scoped_refptr<T>& lhs, std::nullptr_t null) { 403 return !operator==(lhs, null); 404 } 405 406 template <typename T> 407 bool operator!=(std::nullptr_t null, const scoped_refptr<T>& rhs) { 408 return !operator==(null, rhs); 409 } 410 411 template <typename T> 412 std::ostream& operator<<(std::ostream& out, const scoped_refptr<T>& p) { 413 return out << p.get(); 414 } 415 416 template <typename T> 417 void swap(scoped_refptr<T>& lhs, scoped_refptr<T>& rhs) noexcept { 418 lhs.swap(rhs); 419 } 420 421 #endif // BASE_MEMORY_SCOPED_REFPTR_H_ 422