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/macros.h"
     18 #ifndef NDEBUG
     19 #include "base/logging.h"
     20 #endif
     21 #include "base/threading/thread_collision_warner.h"
     22 #include "build/build_config.h"
     23 
     24 namespace base {
     25 
     26 namespace subtle {
     27 
     28 class BASE_EXPORT RefCountedBase {
     29  public:
     30   bool HasOneRef() const { return ref_count_ == 1; }
     31 
     32  protected:
     33   RefCountedBase()
     34       : ref_count_(0)
     35   #ifndef NDEBUG
     36       , in_dtor_(false)
     37   #endif
     38       {
     39   }
     40 
     41   ~RefCountedBase() {
     42   #ifndef NDEBUG
     43     DCHECK(in_dtor_) << "RefCounted object deleted without calling Release()";
     44   #endif
     45   }
     46 
     47 
     48   void AddRef() const {
     49     // TODO(maruel): Add back once it doesn't assert 500 times/sec.
     50     // Current thread books the critical section "AddRelease"
     51     // without release it.
     52     // DFAKE_SCOPED_LOCK_THREAD_LOCKED(add_release_);
     53   #ifndef NDEBUG
     54     DCHECK(!in_dtor_);
     55   #endif
     56     ++ref_count_;
     57   }
     58 
     59   // Returns true if the object should self-delete.
     60   bool Release() const {
     61     // TODO(maruel): Add back once it doesn't assert 500 times/sec.
     62     // Current thread books the critical section "AddRelease"
     63     // without release it.
     64     // DFAKE_SCOPED_LOCK_THREAD_LOCKED(add_release_);
     65   #ifndef NDEBUG
     66     DCHECK(!in_dtor_);
     67   #endif
     68     if (--ref_count_ == 0) {
     69   #ifndef NDEBUG
     70       in_dtor_ = true;
     71   #endif
     72       return true;
     73     }
     74     return false;
     75   }
     76 
     77  private:
     78   mutable int ref_count_;
     79 #ifndef NDEBUG
     80   mutable bool in_dtor_;
     81 #endif
     82 
     83   DFAKE_MUTEX(add_release_);
     84 
     85   DISALLOW_COPY_AND_ASSIGN(RefCountedBase);
     86 };
     87 
     88 class BASE_EXPORT RefCountedThreadSafeBase {
     89  public:
     90   bool HasOneRef() const;
     91 
     92  protected:
     93   RefCountedThreadSafeBase();
     94   ~RefCountedThreadSafeBase();
     95 
     96   void AddRef() const;
     97 
     98   // Returns true if the object should self-delete.
     99   bool Release() const;
    100 
    101  private:
    102   mutable AtomicRefCount ref_count_;
    103 #ifndef NDEBUG
    104   mutable bool in_dtor_;
    105 #endif
    106 
    107   DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafeBase);
    108 };
    109 
    110 }  // namespace subtle
    111 
    112 //
    113 // A base class for reference counted classes.  Otherwise, known as a cheap
    114 // knock-off of WebKit's RefCounted<T> class.  To use this, just extend your
    115 // class from it like so:
    116 //
    117 //   class MyFoo : public base::RefCounted<MyFoo> {
    118 //    ...
    119 //    private:
    120 //     friend class base::RefCounted<MyFoo>;
    121 //     ~MyFoo();
    122 //   };
    123 //
    124 // You should always make your destructor non-public, to avoid any code deleting
    125 // the object accidently while there are references to it.
    126 template <class T>
    127 class RefCounted : public subtle::RefCountedBase {
    128  public:
    129   RefCounted() {}
    130 
    131   void AddRef() const {
    132     subtle::RefCountedBase::AddRef();
    133   }
    134 
    135   void Release() const {
    136     if (subtle::RefCountedBase::Release()) {
    137       delete static_cast<const T*>(this);
    138     }
    139   }
    140 
    141  protected:
    142   ~RefCounted() {}
    143 
    144  private:
    145   DISALLOW_COPY_AND_ASSIGN(RefCounted<T>);
    146 };
    147 
    148 // Forward declaration.
    149 template <class T, typename Traits> class RefCountedThreadSafe;
    150 
    151 // Default traits for RefCountedThreadSafe<T>.  Deletes the object when its ref
    152 // count reaches 0.  Overload to delete it on a different thread etc.
    153 template<typename T>
    154 struct DefaultRefCountedThreadSafeTraits {
    155   static void Destruct(const T* x) {
    156     // Delete through RefCountedThreadSafe to make child classes only need to be
    157     // friend with RefCountedThreadSafe instead of this struct, which is an
    158     // implementation detail.
    159     RefCountedThreadSafe<T,
    160                          DefaultRefCountedThreadSafeTraits>::DeleteInternal(x);
    161   }
    162 };
    163 
    164 //
    165 // A thread-safe variant of RefCounted<T>
    166 //
    167 //   class MyFoo : public base::RefCountedThreadSafe<MyFoo> {
    168 //    ...
    169 //   };
    170 //
    171 // If you're using the default trait, then you should add compile time
    172 // asserts that no one else is deleting your object.  i.e.
    173 //    private:
    174 //     friend class base::RefCountedThreadSafe<MyFoo>;
    175 //     ~MyFoo();
    176 template <class T, typename Traits = DefaultRefCountedThreadSafeTraits<T> >
    177 class RefCountedThreadSafe : public subtle::RefCountedThreadSafeBase {
    178  public:
    179   RefCountedThreadSafe() {}
    180 
    181   void AddRef() const {
    182     subtle::RefCountedThreadSafeBase::AddRef();
    183   }
    184 
    185   void Release() const {
    186     if (subtle::RefCountedThreadSafeBase::Release()) {
    187       Traits::Destruct(static_cast<const T*>(this));
    188     }
    189   }
    190 
    191  protected:
    192   ~RefCountedThreadSafe() {}
    193 
    194  private:
    195   friend struct DefaultRefCountedThreadSafeTraits<T>;
    196   static void DeleteInternal(const T* x) { delete x; }
    197 
    198   DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafe);
    199 };
    200 
    201 //
    202 // A thread-safe wrapper for some piece of data so we can place other
    203 // things in scoped_refptrs<>.
    204 //
    205 template<typename T>
    206 class RefCountedData
    207     : public base::RefCountedThreadSafe< base::RefCountedData<T> > {
    208  public:
    209   RefCountedData() : data() {}
    210   RefCountedData(const T& in_value) : data(in_value) {}
    211 
    212   T data;
    213 
    214  private:
    215   friend class base::RefCountedThreadSafe<base::RefCountedData<T> >;
    216   ~RefCountedData() {}
    217 };
    218 
    219 }  // namespace base
    220 
    221 //
    222 // A smart pointer class for reference counted objects.  Use this class instead
    223 // of calling AddRef and Release manually on a reference counted object to
    224 // avoid common memory leaks caused by forgetting to Release an object
    225 // reference.  Sample usage:
    226 //
    227 //   class MyFoo : public RefCounted<MyFoo> {
    228 //    ...
    229 //   };
    230 //
    231 //   void some_function() {
    232 //     scoped_refptr<MyFoo> foo = new MyFoo();
    233 //     foo->Method(param);
    234 //     // |foo| is released when this function returns
    235 //   }
    236 //
    237 //   void some_other_function() {
    238 //     scoped_refptr<MyFoo> foo = new MyFoo();
    239 //     ...
    240 //     foo = NULL;  // explicitly releases |foo|
    241 //     ...
    242 //     if (foo)
    243 //       foo->Method(param);
    244 //   }
    245 //
    246 // The above examples show how scoped_refptr<T> acts like a pointer to T.
    247 // Given two scoped_refptr<T> classes, it is also possible to exchange
    248 // references between the two objects, like so:
    249 //
    250 //   {
    251 //     scoped_refptr<MyFoo> a = new MyFoo();
    252 //     scoped_refptr<MyFoo> b;
    253 //
    254 //     b.swap(a);
    255 //     // now, |b| references the MyFoo object, and |a| references NULL.
    256 //   }
    257 //
    258 // To make both |a| and |b| in the above example reference the same MyFoo
    259 // object, simply use the assignment operator:
    260 //
    261 //   {
    262 //     scoped_refptr<MyFoo> a = new MyFoo();
    263 //     scoped_refptr<MyFoo> b;
    264 //
    265 //     b = a;
    266 //     // now, |a| and |b| each own a reference to the same MyFoo object.
    267 //   }
    268 //
    269 template <class T>
    270 class scoped_refptr {
    271  public:
    272   typedef T element_type;
    273 
    274   scoped_refptr() : ptr_(NULL) {
    275   }
    276 
    277   scoped_refptr(T* p) : ptr_(p) {
    278     if (ptr_)
    279       AddRef(ptr_);
    280   }
    281 
    282   // Copy constructor.
    283   scoped_refptr(const scoped_refptr<T>& r) : ptr_(r.ptr_) {
    284     if (ptr_)
    285       AddRef(ptr_);
    286   }
    287 
    288   // Copy conversion constructor.
    289   template <typename U,
    290             typename = typename std::enable_if<
    291                 std::is_convertible<U*, T*>::value>::type>
    292   scoped_refptr(const scoped_refptr<U>& r) : ptr_(r.get()) {
    293     if (ptr_)
    294       AddRef(ptr_);
    295   }
    296 
    297   // Move constructor. This is required in addition to the conversion
    298   // constructor below in order for clang to warn about pessimizing moves.
    299   scoped_refptr(scoped_refptr&& r) : ptr_(r.get()) { r.ptr_ = nullptr; }
    300 
    301   // Move conversion constructor.
    302   template <typename U,
    303             typename = typename std::enable_if<
    304                 std::is_convertible<U*, T*>::value>::type>
    305   scoped_refptr(scoped_refptr<U>&& r) : ptr_(r.get()) {
    306     r.ptr_ = nullptr;
    307   }
    308 
    309   ~scoped_refptr() {
    310     if (ptr_)
    311       Release(ptr_);
    312   }
    313 
    314   T* get() const { return ptr_; }
    315 
    316   T& operator*() const {
    317     assert(ptr_ != NULL);
    318     return *ptr_;
    319   }
    320 
    321   T* operator->() const {
    322     assert(ptr_ != NULL);
    323     return ptr_;
    324   }
    325 
    326   scoped_refptr<T>& operator=(T* p) {
    327     // AddRef first so that self assignment should work
    328     if (p)
    329       AddRef(p);
    330     T* old_ptr = ptr_;
    331     ptr_ = p;
    332     if (old_ptr)
    333       Release(old_ptr);
    334     return *this;
    335   }
    336 
    337   scoped_refptr<T>& operator=(const scoped_refptr<T>& r) {
    338     return *this = r.ptr_;
    339   }
    340 
    341   template <typename U>
    342   scoped_refptr<T>& operator=(const scoped_refptr<U>& r) {
    343     return *this = r.get();
    344   }
    345 
    346   scoped_refptr<T>& operator=(scoped_refptr<T>&& r) {
    347     scoped_refptr<T>(std::move(r)).swap(*this);
    348     return *this;
    349   }
    350 
    351   template <typename U>
    352   scoped_refptr<T>& operator=(scoped_refptr<U>&& r) {
    353     scoped_refptr<T>(std::move(r)).swap(*this);
    354     return *this;
    355   }
    356 
    357   void swap(T** pp) {
    358     T* p = ptr_;
    359     ptr_ = *pp;
    360     *pp = p;
    361   }
    362 
    363   void swap(scoped_refptr<T>& r) {
    364     swap(&r.ptr_);
    365   }
    366 
    367   explicit operator bool() const { return ptr_ != nullptr; }
    368 
    369   template <typename U>
    370   bool operator==(const scoped_refptr<U>& rhs) const {
    371     return ptr_ == rhs.get();
    372   }
    373 
    374   template <typename U>
    375   bool operator!=(const scoped_refptr<U>& rhs) const {
    376     return !operator==(rhs);
    377   }
    378 
    379   template <typename U>
    380   bool operator<(const scoped_refptr<U>& rhs) const {
    381     return ptr_ < rhs.get();
    382   }
    383 
    384  protected:
    385   T* ptr_;
    386 
    387  private:
    388   // Friend required for move constructors that set r.ptr_ to null.
    389   template <typename U>
    390   friend class scoped_refptr;
    391 
    392   // Non-inline helpers to allow:
    393   //     class Opaque;
    394   //     extern template class scoped_refptr<Opaque>;
    395   // Otherwise the compiler will complain that Opaque is an incomplete type.
    396   static void AddRef(T* ptr);
    397   static void Release(T* ptr);
    398 };
    399 
    400 template <typename T>
    401 void scoped_refptr<T>::AddRef(T* ptr) {
    402   ptr->AddRef();
    403 }
    404 
    405 template <typename T>
    406 void scoped_refptr<T>::Release(T* ptr) {
    407   ptr->Release();
    408 }
    409 
    410 // Handy utility for creating a scoped_refptr<T> out of a T* explicitly without
    411 // having to retype all the template arguments
    412 template <typename T>
    413 scoped_refptr<T> make_scoped_refptr(T* t) {
    414   return scoped_refptr<T>(t);
    415 }
    416 
    417 template <typename T, typename U>
    418 bool operator==(const scoped_refptr<T>& lhs, const U* rhs) {
    419   return lhs.get() == rhs;
    420 }
    421 
    422 template <typename T, typename U>
    423 bool operator==(const T* lhs, const scoped_refptr<U>& rhs) {
    424   return lhs == rhs.get();
    425 }
    426 
    427 template <typename T>
    428 bool operator==(const scoped_refptr<T>& lhs, std::nullptr_t) {
    429   return !static_cast<bool>(lhs);
    430 }
    431 
    432 template <typename T>
    433 bool operator==(std::nullptr_t, const scoped_refptr<T>& rhs) {
    434   return !static_cast<bool>(rhs);
    435 }
    436 
    437 template <typename T, typename U>
    438 bool operator!=(const scoped_refptr<T>& lhs, const U* rhs) {
    439   return !operator==(lhs, rhs);
    440 }
    441 
    442 template <typename T, typename U>
    443 bool operator!=(const T* lhs, const scoped_refptr<U>& rhs) {
    444   return !operator==(lhs, rhs);
    445 }
    446 
    447 template <typename T>
    448 bool operator!=(const scoped_refptr<T>& lhs, std::nullptr_t null) {
    449   return !operator==(lhs, null);
    450 }
    451 
    452 template <typename T>
    453 bool operator!=(std::nullptr_t null, const scoped_refptr<T>& rhs) {
    454   return !operator==(null, rhs);
    455 }
    456 
    457 template <typename T>
    458 std::ostream& operator<<(std::ostream& out, const scoped_refptr<T>& p) {
    459   return out << p.get();
    460 }
    461 
    462 #endif  // BASE_MEMORY_REF_COUNTED_H_
    463