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