Home | History | Annotate | Download | only in memory
      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:
     39   bool HasOneRef() const { return ref_count_ == 1; }
     40 
     41  protected:
     42   explicit RefCountedBase(StartRefCountFromZeroTag) {
     43 #if DCHECK_IS_ON()
     44     sequence_checker_.DetachFromSequence();
     45 #endif
     46   }
     47 
     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 
     55   ~RefCountedBase() {
     56 #if DCHECK_IS_ON()
     57     DCHECK(in_dtor_) << "RefCounted object deleted without calling Release()";
     58 #endif
     59   }
     60 
     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.
     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 
    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:
    136   explicit RefCountedThreadSafeBase(StartRefCountFromZeroTag) {}
    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 
    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 
    245   RefCounted() : subtle::RefCountedBase(T::kRefCountPreference) {}
    246 
    247   void AddRef() const {
    248     subtle::RefCountedBase::AddRef();
    249   }
    250 
    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 {
    271   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 
    301   explicit RefCountedThreadSafe()
    302       : subtle::RefCountedThreadSafeBase(T::kRefCountPreference) {}
    303 
    304   void AddRef() const {
    305     subtle::RefCountedThreadSafeBase::AddRef();
    306   }
    307 
    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