1 // Copyright (c) 2012 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_REF_COUNTED_H_ 6 #define BASE_MEMORY_REF_COUNTED_H_ 7 8 #include <stddef.h> 9 10 #include <cassert> 11 #include <iosfwd> 12 #include <type_traits> 13 14 #include "base/atomic_ref_count.h" 15 #include "base/base_export.h" 16 #include "base/compiler_specific.h" 17 #include "base/logging.h" 18 #include "base/macros.h" 19 #include "base/sequence_checker.h" 20 #include "base/threading/thread_collision_warner.h" 21 #include "build/build_config.h" 22 23 template <class T> 24 class scoped_refptr; 25 26 namespace base { 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 class BASE_EXPORT RefCountedBase { 38 public: HasOneRef()39 bool HasOneRef() const { return ref_count_ == 1; } 40 41 protected: RefCountedBase(StartRefCountFromZeroTag)42 explicit RefCountedBase(StartRefCountFromZeroTag) { 43 #if DCHECK_IS_ON() 44 sequence_checker_.DetachFromSequence(); 45 #endif 46 } 47 RefCountedBase(StartRefCountFromOneTag)48 explicit RefCountedBase(StartRefCountFromOneTag) : ref_count_(1) { 49 #if DCHECK_IS_ON() 50 needs_adopt_ref_ = true; 51 sequence_checker_.DetachFromSequence(); 52 #endif 53 } 54 ~RefCountedBase()55 ~RefCountedBase() { 56 #if DCHECK_IS_ON() 57 DCHECK(in_dtor_) << "RefCounted object deleted without calling Release()"; 58 #endif 59 } 60 AddRef()61 void AddRef() const { 62 // TODO(maruel): Add back once it doesn't assert 500 times/sec. 63 // Current thread books the critical section "AddRelease" 64 // without release it. 65 // DFAKE_SCOPED_LOCK_THREAD_LOCKED(add_release_); 66 #if DCHECK_IS_ON() 67 DCHECK(!in_dtor_); 68 DCHECK(!needs_adopt_ref_) 69 << "This RefCounted object is created with non-zero reference count." 70 << " The first reference to such a object has to be made by AdoptRef or" 71 << " MakeShared."; 72 if (ref_count_ >= 1) { 73 DCHECK(CalledOnValidSequence()); 74 } 75 #endif 76 77 ++ref_count_; 78 } 79 80 // Returns true if the object should self-delete. Release()81 bool Release() const { 82 --ref_count_; 83 84 // TODO(maruel): Add back once it doesn't assert 500 times/sec. 85 // Current thread books the critical section "AddRelease" 86 // without release it. 87 // DFAKE_SCOPED_LOCK_THREAD_LOCKED(add_release_); 88 89 #if DCHECK_IS_ON() 90 DCHECK(!in_dtor_); 91 if (ref_count_ == 0) 92 in_dtor_ = true; 93 94 if (ref_count_ >= 1) 95 DCHECK(CalledOnValidSequence()); 96 if (ref_count_ == 1) 97 sequence_checker_.DetachFromSequence(); 98 #endif 99 100 return ref_count_ == 0; 101 } 102 103 private: 104 template <typename U> 105 friend scoped_refptr<U> base::AdoptRef(U*); 106 Adopted()107 void Adopted() const { 108 #if DCHECK_IS_ON() 109 DCHECK(needs_adopt_ref_); 110 needs_adopt_ref_ = false; 111 #endif 112 } 113 114 #if DCHECK_IS_ON() 115 bool CalledOnValidSequence() const; 116 #endif 117 118 mutable size_t ref_count_ = 0; 119 120 #if DCHECK_IS_ON() 121 mutable bool needs_adopt_ref_ = false; 122 mutable bool in_dtor_ = false; 123 mutable SequenceChecker sequence_checker_; 124 #endif 125 126 DFAKE_MUTEX(add_release_); 127 128 DISALLOW_COPY_AND_ASSIGN(RefCountedBase); 129 }; 130 131 class BASE_EXPORT RefCountedThreadSafeBase { 132 public: 133 bool HasOneRef() const; 134 135 protected: RefCountedThreadSafeBase(StartRefCountFromZeroTag)136 explicit RefCountedThreadSafeBase(StartRefCountFromZeroTag) {} RefCountedThreadSafeBase(StartRefCountFromOneTag)137 explicit RefCountedThreadSafeBase(StartRefCountFromOneTag) : ref_count_(1) { 138 #if DCHECK_IS_ON() 139 needs_adopt_ref_ = true; 140 #endif 141 } 142 143 ~RefCountedThreadSafeBase(); 144 145 void AddRef() const; 146 147 // Returns true if the object should self-delete. 148 bool Release() const; 149 150 private: 151 template <typename U> 152 friend scoped_refptr<U> base::AdoptRef(U*); 153 Adopted()154 void Adopted() const { 155 #if DCHECK_IS_ON() 156 DCHECK(needs_adopt_ref_); 157 needs_adopt_ref_ = false; 158 #endif 159 } 160 161 mutable AtomicRefCount ref_count_ = 0; 162 #if DCHECK_IS_ON() 163 mutable bool needs_adopt_ref_ = false; 164 mutable bool in_dtor_ = false; 165 #endif 166 167 DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafeBase); 168 }; 169 170 } // namespace subtle 171 172 // ScopedAllowCrossThreadRefCountAccess disables the check documented on 173 // RefCounted below for rare pre-existing use cases where thread-safety was 174 // guaranteed through other means (e.g. explicit sequencing of calls across 175 // execution sequences when bouncing between threads in order). New callers 176 // should refrain from using this (callsites handling thread-safety through 177 // locks should use RefCountedThreadSafe per the overhead of its atomics being 178 // negligible compared to locks anyways and callsites doing explicit sequencing 179 // should properly std::move() the ref to avoid hitting this check). 180 // TODO(tzik): Cleanup existing use cases and remove 181 // ScopedAllowCrossThreadRefCountAccess. 182 class BASE_EXPORT ScopedAllowCrossThreadRefCountAccess final { 183 public: 184 #if DCHECK_IS_ON() 185 ScopedAllowCrossThreadRefCountAccess(); 186 ~ScopedAllowCrossThreadRefCountAccess(); 187 #else 188 ScopedAllowCrossThreadRefCountAccess() {} 189 ~ScopedAllowCrossThreadRefCountAccess() {} 190 #endif 191 }; 192 193 // 194 // A base class for reference counted classes. Otherwise, known as a cheap 195 // knock-off of WebKit's RefCounted<T> class. To use this, just extend your 196 // class from it like so: 197 // 198 // class MyFoo : public base::RefCounted<MyFoo> { 199 // ... 200 // private: 201 // friend class base::RefCounted<MyFoo>; 202 // ~MyFoo(); 203 // }; 204 // 205 // You should always make your destructor non-public, to avoid any code deleting 206 // the object accidently while there are references to it. 207 // 208 // 209 // The ref count manipulation to RefCounted is NOT thread safe and has DCHECKs 210 // to trap unsafe cross thread usage. A subclass instance of RefCounted can be 211 // passed to another execution sequence only when its ref count is 1. If the ref 212 // count is more than 1, the RefCounted class verifies the ref updates are made 213 // on the same execution sequence as the previous ones. 214 // 215 // 216 // The reference count starts from zero by default, and we intended to migrate 217 // to start-from-one ref count. Put REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE() to 218 // the ref counted class to opt-in. 219 // 220 // If an object has start-from-one ref count, the first scoped_refptr need to be 221 // created by base::AdoptRef() or base::MakeShared(). We can use 222 // base::MakeShared() to create create both type of ref counted object. 223 // 224 // The motivations to use start-from-one ref count are: 225 // - Start-from-one ref count doesn't need the ref count increment for the 226 // first reference. 227 // - It can detect an invalid object acquisition for a being-deleted object 228 // that has zero ref count. That tends to happen on custom deleter that 229 // delays the deletion. 230 // TODO(tzik): Implement invalid acquisition detection. 231 // - Behavior parity to Blink's WTF::RefCounted, whose count starts from one. 232 // And start-from-one ref count is a step to merge WTF::RefCounted into 233 // base::RefCounted. 234 // 235 #define REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE() \ 236 static constexpr ::base::subtle::StartRefCountFromOneTag \ 237 kRefCountPreference = ::base::subtle::kStartRefCountFromOneTag 238 239 template <class T> 240 class RefCounted : public subtle::RefCountedBase { 241 public: 242 static constexpr subtle::StartRefCountFromZeroTag kRefCountPreference = 243 subtle::kStartRefCountFromZeroTag; 244 RefCounted()245 RefCounted() : subtle::RefCountedBase(T::kRefCountPreference) {} 246 AddRef()247 void AddRef() const { 248 subtle::RefCountedBase::AddRef(); 249 } 250 Release()251 void Release() const { 252 if (subtle::RefCountedBase::Release()) { 253 delete static_cast<const T*>(this); 254 } 255 } 256 257 protected: 258 ~RefCounted() = default; 259 260 private: 261 DISALLOW_COPY_AND_ASSIGN(RefCounted); 262 }; 263 264 // Forward declaration. 265 template <class T, typename Traits> class RefCountedThreadSafe; 266 267 // Default traits for RefCountedThreadSafe<T>. Deletes the object when its ref 268 // count reaches 0. Overload to delete it on a different thread etc. 269 template<typename T> 270 struct DefaultRefCountedThreadSafeTraits { DestructDefaultRefCountedThreadSafeTraits271 static void Destruct(const T* x) { 272 // Delete through RefCountedThreadSafe to make child classes only need to be 273 // friend with RefCountedThreadSafe instead of this struct, which is an 274 // implementation detail. 275 RefCountedThreadSafe<T, 276 DefaultRefCountedThreadSafeTraits>::DeleteInternal(x); 277 } 278 }; 279 280 // 281 // A thread-safe variant of RefCounted<T> 282 // 283 // class MyFoo : public base::RefCountedThreadSafe<MyFoo> { 284 // ... 285 // }; 286 // 287 // If you're using the default trait, then you should add compile time 288 // asserts that no one else is deleting your object. i.e. 289 // private: 290 // friend class base::RefCountedThreadSafe<MyFoo>; 291 // ~MyFoo(); 292 // 293 // We can use REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE() with RefCountedThreadSafe 294 // too. See the comment above the RefCounted definition for details. 295 template <class T, typename Traits = DefaultRefCountedThreadSafeTraits<T> > 296 class RefCountedThreadSafe : public subtle::RefCountedThreadSafeBase { 297 public: 298 static constexpr subtle::StartRefCountFromZeroTag kRefCountPreference = 299 subtle::kStartRefCountFromZeroTag; 300 RefCountedThreadSafe()301 explicit RefCountedThreadSafe() 302 : subtle::RefCountedThreadSafeBase(T::kRefCountPreference) {} 303 AddRef()304 void AddRef() const { 305 subtle::RefCountedThreadSafeBase::AddRef(); 306 } 307 Release()308 void Release() const { 309 if (subtle::RefCountedThreadSafeBase::Release()) { 310 Traits::Destruct(static_cast<const T*>(this)); 311 } 312 } 313 314 protected: 315 ~RefCountedThreadSafe() = default; 316 317 private: 318 friend struct DefaultRefCountedThreadSafeTraits<T>; 319 static void DeleteInternal(const T* x) { delete x; } 320 321 DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafe); 322 }; 323 324 // 325 // A thread-safe wrapper for some piece of data so we can place other 326 // things in scoped_refptrs<>. 327 // 328 template<typename T> 329 class RefCountedData 330 : public base::RefCountedThreadSafe< base::RefCountedData<T> > { 331 public: 332 RefCountedData() : data() {} 333 RefCountedData(const T& in_value) : data(in_value) {} 334 335 T data; 336 337 private: 338 friend class base::RefCountedThreadSafe<base::RefCountedData<T> >; 339 ~RefCountedData() = default; 340 }; 341 342 // Creates a scoped_refptr from a raw pointer without incrementing the reference 343 // count. Use this only for a newly created object whose reference count starts 344 // from 1 instead of 0. 345 template <typename T> 346 scoped_refptr<T> AdoptRef(T* obj) { 347 using Tag = typename std::decay<decltype(T::kRefCountPreference)>::type; 348 static_assert(std::is_same<subtle::StartRefCountFromOneTag, Tag>::value, 349 "Use AdoptRef only for the reference count starts from one."); 350 351 DCHECK(obj); 352 DCHECK(obj->HasOneRef()); 353 obj->Adopted(); 354 return scoped_refptr<T>(obj, subtle::kAdoptRefTag); 355 } 356 357 namespace subtle { 358 359 template <typename T> 360 scoped_refptr<T> AdoptRefIfNeeded(T* obj, StartRefCountFromZeroTag) { 361 return scoped_refptr<T>(obj); 362 } 363 364 template <typename T> 365 scoped_refptr<T> AdoptRefIfNeeded(T* obj, StartRefCountFromOneTag) { 366 return AdoptRef(obj); 367 } 368 369 } // namespace subtle 370 371 // Constructs an instance of T, which is a ref counted type, and wraps the 372 // object into a scoped_refptr. 373 template <typename T, typename... Args> 374 scoped_refptr<T> MakeShared(Args&&... args) { 375 T* obj = new T(std::forward<Args>(args)...); 376 return subtle::AdoptRefIfNeeded(obj, T::kRefCountPreference); 377 } 378 379 } // namespace base 380 381 // 382 // A smart pointer class for reference counted objects. Use this class instead 383 // of calling AddRef and Release manually on a reference counted object to 384 // avoid common memory leaks caused by forgetting to Release an object 385 // reference. Sample usage: 386 // 387 // class MyFoo : public RefCounted<MyFoo> { 388 // ... 389 // private: 390 // friend class RefCounted<MyFoo>; // Allow destruction by RefCounted<>. 391 // ~MyFoo(); // Destructor must be private/protected. 392 // }; 393 // 394 // void some_function() { 395 // scoped_refptr<MyFoo> foo = new MyFoo(); 396 // foo->Method(param); 397 // // |foo| is released when this function returns 398 // } 399 // 400 // void some_other_function() { 401 // scoped_refptr<MyFoo> foo = new MyFoo(); 402 // ... 403 // foo = nullptr; // explicitly releases |foo| 404 // ... 405 // if (foo) 406 // foo->Method(param); 407 // } 408 // 409 // The above examples show how scoped_refptr<T> acts like a pointer to T. 410 // Given two scoped_refptr<T> classes, it is also possible to exchange 411 // references between the two objects, like so: 412 // 413 // { 414 // scoped_refptr<MyFoo> a = new MyFoo(); 415 // scoped_refptr<MyFoo> b; 416 // 417 // b.swap(a); 418 // // now, |b| references the MyFoo object, and |a| references nullptr. 419 // } 420 // 421 // To make both |a| and |b| in the above example reference the same MyFoo 422 // object, simply use the assignment operator: 423 // 424 // { 425 // scoped_refptr<MyFoo> a = new MyFoo(); 426 // scoped_refptr<MyFoo> b; 427 // 428 // b = a; 429 // // now, |a| and |b| each own a reference to the same MyFoo object. 430 // } 431 // 432 template <class T> 433 class scoped_refptr { 434 public: 435 typedef T element_type; 436 437 scoped_refptr() {} 438 439 scoped_refptr(T* p) : ptr_(p) { 440 if (ptr_) 441 AddRef(ptr_); 442 } 443 444 // Copy constructor. 445 scoped_refptr(const scoped_refptr<T>& r) : ptr_(r.ptr_) { 446 if (ptr_) 447 AddRef(ptr_); 448 } 449 450 // Copy conversion constructor. 451 template <typename U, 452 typename = typename std::enable_if< 453 std::is_convertible<U*, T*>::value>::type> 454 scoped_refptr(const scoped_refptr<U>& r) : ptr_(r.get()) { 455 if (ptr_) 456 AddRef(ptr_); 457 } 458 459 // Move constructor. This is required in addition to the conversion 460 // constructor below in order for clang to warn about pessimizing moves. 461 scoped_refptr(scoped_refptr&& r) : ptr_(r.get()) { r.ptr_ = nullptr; } 462 463 // Move conversion constructor. 464 template <typename U, 465 typename = typename std::enable_if< 466 std::is_convertible<U*, T*>::value>::type> 467 scoped_refptr(scoped_refptr<U>&& r) : ptr_(r.get()) { 468 r.ptr_ = nullptr; 469 } 470 471 ~scoped_refptr() { 472 if (ptr_) 473 Release(ptr_); 474 } 475 476 T* get() const { return ptr_; } 477 478 T& operator*() const { 479 assert(ptr_ != nullptr); 480 return *ptr_; 481 } 482 483 T* operator->() const { 484 assert(ptr_ != nullptr); 485 return ptr_; 486 } 487 488 scoped_refptr<T>& operator=(T* p) { 489 // AddRef first so that self assignment should work 490 if (p) 491 AddRef(p); 492 T* old_ptr = ptr_; 493 ptr_ = p; 494 if (old_ptr) 495 Release(old_ptr); 496 return *this; 497 } 498 499 scoped_refptr<T>& operator=(const scoped_refptr<T>& r) { 500 return *this = r.ptr_; 501 } 502 503 template <typename U> 504 scoped_refptr<T>& operator=(const scoped_refptr<U>& r) { 505 return *this = r.get(); 506 } 507 508 scoped_refptr<T>& operator=(scoped_refptr<T>&& r) { 509 scoped_refptr<T>(std::move(r)).swap(*this); 510 return *this; 511 } 512 513 template <typename U> 514 scoped_refptr<T>& operator=(scoped_refptr<U>&& r) { 515 scoped_refptr<T>(std::move(r)).swap(*this); 516 return *this; 517 } 518 519 void swap(scoped_refptr<T>& r) { 520 T* tmp = ptr_; 521 ptr_ = r.ptr_; 522 r.ptr_ = tmp; 523 } 524 525 explicit operator bool() const { return ptr_ != nullptr; } 526 527 template <typename U> 528 bool operator==(const scoped_refptr<U>& rhs) const { 529 return ptr_ == rhs.get(); 530 } 531 532 template <typename U> 533 bool operator!=(const scoped_refptr<U>& rhs) const { 534 return !operator==(rhs); 535 } 536 537 template <typename U> 538 bool operator<(const scoped_refptr<U>& rhs) const { 539 return ptr_ < rhs.get(); 540 } 541 542 protected: 543 T* ptr_ = nullptr; 544 545 private: 546 template <typename U> 547 friend scoped_refptr<U> base::AdoptRef(U*); 548 549 scoped_refptr(T* p, base::subtle::AdoptRefTag) : ptr_(p) {} 550 551 // Friend required for move constructors that set r.ptr_ to null. 552 template <typename U> 553 friend class scoped_refptr; 554 555 // Non-inline helpers to allow: 556 // class Opaque; 557 // extern template class scoped_refptr<Opaque>; 558 // Otherwise the compiler will complain that Opaque is an incomplete type. 559 static void AddRef(T* ptr); 560 static void Release(T* ptr); 561 }; 562 563 // static 564 template <typename T> 565 void scoped_refptr<T>::AddRef(T* ptr) { 566 ptr->AddRef(); 567 } 568 569 // static 570 template <typename T> 571 void scoped_refptr<T>::Release(T* ptr) { 572 ptr->Release(); 573 } 574 575 // Handy utility for creating a scoped_refptr<T> out of a T* explicitly without 576 // having to retype all the template arguments 577 template <typename T> 578 scoped_refptr<T> make_scoped_refptr(T* t) { 579 return scoped_refptr<T>(t); 580 } 581 582 template <typename T, typename U> 583 bool operator==(const scoped_refptr<T>& lhs, const U* rhs) { 584 return lhs.get() == rhs; 585 } 586 587 template <typename T, typename U> 588 bool operator==(const T* lhs, const scoped_refptr<U>& rhs) { 589 return lhs == rhs.get(); 590 } 591 592 template <typename T> 593 bool operator==(const scoped_refptr<T>& lhs, std::nullptr_t null) { 594 return !static_cast<bool>(lhs); 595 } 596 597 template <typename T> 598 bool operator==(std::nullptr_t null, const scoped_refptr<T>& rhs) { 599 return !static_cast<bool>(rhs); 600 } 601 602 template <typename T, typename U> 603 bool operator!=(const scoped_refptr<T>& lhs, const U* rhs) { 604 return !operator==(lhs, rhs); 605 } 606 607 template <typename T, typename U> 608 bool operator!=(const T* lhs, const scoped_refptr<U>& rhs) { 609 return !operator==(lhs, rhs); 610 } 611 612 template <typename T> 613 bool operator!=(const scoped_refptr<T>& lhs, std::nullptr_t null) { 614 return !operator==(lhs, null); 615 } 616 617 template <typename T> 618 bool operator!=(std::nullptr_t null, const scoped_refptr<T>& rhs) { 619 return !operator==(null, rhs); 620 } 621 622 template <typename T> 623 std::ostream& operator<<(std::ostream& out, const scoped_refptr<T>& p) { 624 return out << p.get(); 625 } 626 627 #endif // BASE_MEMORY_REF_COUNTED_H_ 628