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 <cassert>
      9 
     10 #include "base/atomic_ref_count.h"
     11 #include "base/base_export.h"
     12 #include "base/compiler_specific.h"
     13 #ifndef NDEBUG
     14 #include "base/logging.h"
     15 #endif
     16 #include "base/threading/thread_collision_warner.h"
     17 
     18 namespace base {
     19 
     20 namespace subtle {
     21 
     22 class BASE_EXPORT RefCountedBase {
     23  public:
     24   bool HasOneRef() const { return ref_count_ == 1; }
     25 
     26  protected:
     27   RefCountedBase()
     28       : ref_count_(0)
     29   #ifndef NDEBUG
     30       , in_dtor_(false)
     31   #endif
     32       {
     33   }
     34 
     35   ~RefCountedBase() {
     36   #ifndef NDEBUG
     37     DCHECK(in_dtor_) << "RefCounted object deleted without calling Release()";
     38   #endif
     39   }
     40 
     41 
     42   void AddRef() const {
     43     // TODO(maruel): Add back once it doesn't assert 500 times/sec.
     44     // Current thread books the critical section "AddRelease"
     45     // without release it.
     46     // DFAKE_SCOPED_LOCK_THREAD_LOCKED(add_release_);
     47   #ifndef NDEBUG
     48     DCHECK(!in_dtor_);
     49   #endif
     50     ++ref_count_;
     51   }
     52 
     53   // Returns true if the object should self-delete.
     54   bool Release() const {
     55     // TODO(maruel): Add back once it doesn't assert 500 times/sec.
     56     // Current thread books the critical section "AddRelease"
     57     // without release it.
     58     // DFAKE_SCOPED_LOCK_THREAD_LOCKED(add_release_);
     59   #ifndef NDEBUG
     60     DCHECK(!in_dtor_);
     61   #endif
     62     if (--ref_count_ == 0) {
     63   #ifndef NDEBUG
     64       in_dtor_ = true;
     65   #endif
     66       return true;
     67     }
     68     return false;
     69   }
     70 
     71  private:
     72   mutable int ref_count_;
     73 #ifndef NDEBUG
     74   mutable bool in_dtor_;
     75 #endif
     76 
     77   DFAKE_MUTEX(add_release_);
     78 
     79   DISALLOW_COPY_AND_ASSIGN(RefCountedBase);
     80 };
     81 
     82 class BASE_EXPORT RefCountedThreadSafeBase {
     83  public:
     84   bool HasOneRef() const;
     85 
     86  protected:
     87   RefCountedThreadSafeBase();
     88   ~RefCountedThreadSafeBase();
     89 
     90   void AddRef() const;
     91 
     92   // Returns true if the object should self-delete.
     93   bool Release() const;
     94 
     95  private:
     96   mutable AtomicRefCount ref_count_;
     97 #ifndef NDEBUG
     98   mutable bool in_dtor_;
     99 #endif
    100 
    101   DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafeBase);
    102 };
    103 
    104 }  // namespace subtle
    105 
    106 //
    107 // A base class for reference counted classes.  Otherwise, known as a cheap
    108 // knock-off of WebKit's RefCounted<T> class.  To use this guy just extend your
    109 // class from it like so:
    110 //
    111 //   class MyFoo : public base::RefCounted<MyFoo> {
    112 //    ...
    113 //    private:
    114 //     friend class base::RefCounted<MyFoo>;
    115 //     ~MyFoo();
    116 //   };
    117 //
    118 // You should always make your destructor private, to avoid any code deleting
    119 // the object accidently while there are references to it.
    120 template <class T>
    121 class RefCounted : public subtle::RefCountedBase {
    122  public:
    123   RefCounted() {}
    124 
    125   void AddRef() const {
    126     subtle::RefCountedBase::AddRef();
    127   }
    128 
    129   void Release() const {
    130     if (subtle::RefCountedBase::Release()) {
    131       delete static_cast<const T*>(this);
    132     }
    133   }
    134 
    135  protected:
    136   ~RefCounted() {}
    137 
    138  private:
    139   DISALLOW_COPY_AND_ASSIGN(RefCounted<T>);
    140 };
    141 
    142 // Forward declaration.
    143 template <class T, typename Traits> class RefCountedThreadSafe;
    144 
    145 // Default traits for RefCountedThreadSafe<T>.  Deletes the object when its ref
    146 // count reaches 0.  Overload to delete it on a different thread etc.
    147 template<typename T>
    148 struct DefaultRefCountedThreadSafeTraits {
    149   static void Destruct(const T* x) {
    150     // Delete through RefCountedThreadSafe to make child classes only need to be
    151     // friend with RefCountedThreadSafe instead of this struct, which is an
    152     // implementation detail.
    153     RefCountedThreadSafe<T,
    154                          DefaultRefCountedThreadSafeTraits>::DeleteInternal(x);
    155   }
    156 };
    157 
    158 //
    159 // A thread-safe variant of RefCounted<T>
    160 //
    161 //   class MyFoo : public base::RefCountedThreadSafe<MyFoo> {
    162 //    ...
    163 //   };
    164 //
    165 // If you're using the default trait, then you should add compile time
    166 // asserts that no one else is deleting your object.  i.e.
    167 //    private:
    168 //     friend class base::RefCountedThreadSafe<MyFoo>;
    169 //     ~MyFoo();
    170 template <class T, typename Traits = DefaultRefCountedThreadSafeTraits<T> >
    171 class RefCountedThreadSafe : public subtle::RefCountedThreadSafeBase {
    172  public:
    173   RefCountedThreadSafe() {}
    174 
    175   void AddRef() const {
    176     subtle::RefCountedThreadSafeBase::AddRef();
    177   }
    178 
    179   void Release() const {
    180     if (subtle::RefCountedThreadSafeBase::Release()) {
    181       Traits::Destruct(static_cast<const T*>(this));
    182     }
    183   }
    184 
    185  protected:
    186   ~RefCountedThreadSafe() {}
    187 
    188  private:
    189   friend struct DefaultRefCountedThreadSafeTraits<T>;
    190   static void DeleteInternal(const T* x) { delete x; }
    191 
    192   DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafe);
    193 };
    194 
    195 //
    196 // A thread-safe wrapper for some piece of data so we can place other
    197 // things in scoped_refptrs<>.
    198 //
    199 template<typename T>
    200 class RefCountedData
    201     : public base::RefCountedThreadSafe< base::RefCountedData<T> > {
    202  public:
    203   RefCountedData() : data() {}
    204   RefCountedData(const T& in_value) : data(in_value) {}
    205 
    206   T data;
    207 
    208  private:
    209   friend class base::RefCountedThreadSafe<base::RefCountedData<T> >;
    210   ~RefCountedData() {}
    211 };
    212 
    213 }  // namespace base
    214 
    215 //
    216 // A smart pointer class for reference counted objects.  Use this class instead
    217 // of calling AddRef and Release manually on a reference counted object to
    218 // avoid common memory leaks caused by forgetting to Release an object
    219 // reference.  Sample usage:
    220 //
    221 //   class MyFoo : public RefCounted<MyFoo> {
    222 //    ...
    223 //   };
    224 //
    225 //   void some_function() {
    226 //     scoped_refptr<MyFoo> foo = new MyFoo();
    227 //     foo->Method(param);
    228 //     // |foo| is released when this function returns
    229 //   }
    230 //
    231 //   void some_other_function() {
    232 //     scoped_refptr<MyFoo> foo = new MyFoo();
    233 //     ...
    234 //     foo = NULL;  // explicitly releases |foo|
    235 //     ...
    236 //     if (foo)
    237 //       foo->Method(param);
    238 //   }
    239 //
    240 // The above examples show how scoped_refptr<T> acts like a pointer to T.
    241 // Given two scoped_refptr<T> classes, it is also possible to exchange
    242 // references between the two objects, like so:
    243 //
    244 //   {
    245 //     scoped_refptr<MyFoo> a = new MyFoo();
    246 //     scoped_refptr<MyFoo> b;
    247 //
    248 //     b.swap(a);
    249 //     // now, |b| references the MyFoo object, and |a| references NULL.
    250 //   }
    251 //
    252 // To make both |a| and |b| in the above example reference the same MyFoo
    253 // object, simply use the assignment operator:
    254 //
    255 //   {
    256 //     scoped_refptr<MyFoo> a = new MyFoo();
    257 //     scoped_refptr<MyFoo> b;
    258 //
    259 //     b = a;
    260 //     // now, |a| and |b| each own a reference to the same MyFoo object.
    261 //   }
    262 //
    263 template <class T>
    264 class scoped_refptr {
    265  public:
    266   typedef T element_type;
    267 
    268   scoped_refptr() : ptr_(NULL) {
    269   }
    270 
    271   scoped_refptr(T* p) : ptr_(p) {
    272     if (ptr_)
    273       ptr_->AddRef();
    274   }
    275 
    276   scoped_refptr(const scoped_refptr<T>& r) : ptr_(r.ptr_) {
    277     if (ptr_)
    278       ptr_->AddRef();
    279   }
    280 
    281   template <typename U>
    282   scoped_refptr(const scoped_refptr<U>& r) : ptr_(r.get()) {
    283     if (ptr_)
    284       ptr_->AddRef();
    285   }
    286 
    287   ~scoped_refptr() {
    288     if (ptr_)
    289       ptr_->Release();
    290   }
    291 
    292   T* get() const { return ptr_; }
    293 
    294   // Allow scoped_refptr<C> to be used in boolean expression
    295   // and comparison operations.
    296   operator T*() const { return ptr_; }
    297 
    298   T* operator->() const {
    299     assert(ptr_ != NULL);
    300     return ptr_;
    301   }
    302 
    303   scoped_refptr<T>& operator=(T* p) {
    304     // AddRef first so that self assignment should work
    305     if (p)
    306       p->AddRef();
    307     T* old_ptr = ptr_;
    308     ptr_ = p;
    309     if (old_ptr)
    310       old_ptr->Release();
    311     return *this;
    312   }
    313 
    314   scoped_refptr<T>& operator=(const scoped_refptr<T>& r) {
    315     return *this = r.ptr_;
    316   }
    317 
    318   template <typename U>
    319   scoped_refptr<T>& operator=(const scoped_refptr<U>& r) {
    320     return *this = r.get();
    321   }
    322 
    323   void swap(T** pp) {
    324     T* p = ptr_;
    325     ptr_ = *pp;
    326     *pp = p;
    327   }
    328 
    329   void swap(scoped_refptr<T>& r) {
    330     swap(&r.ptr_);
    331   }
    332 
    333  protected:
    334   T* ptr_;
    335 };
    336 
    337 // Handy utility for creating a scoped_refptr<T> out of a T* explicitly without
    338 // having to retype all the template arguments
    339 template <typename T>
    340 scoped_refptr<T> make_scoped_refptr(T* t) {
    341   return scoped_refptr<T>(t);
    342 }
    343 
    344 #endif  // BASE_MEMORY_REF_COUNTED_H_
    345