Home | History | Annotate | Download | only in memory
      1 // Copyright (c) 2011 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 #pragma once
      8 
      9 #include "base/atomic_ref_count.h"
     10 #include "base/base_api.h"
     11 #include "base/threading/thread_collision_warner.h"
     12 
     13 namespace base {
     14 
     15 namespace subtle {
     16 
     17 class BASE_API RefCountedBase {
     18  public:
     19   static bool ImplementsThreadSafeReferenceCounting() { return false; }
     20 
     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_API RefCountedThreadSafeBase {
     44  public:
     45   static bool ImplementsThreadSafeReferenceCounting() { return true; }
     46 
     47   bool HasOneRef() const;
     48 
     49  protected:
     50   RefCountedThreadSafeBase();
     51   ~RefCountedThreadSafeBase();
     52 
     53   void AddRef() const;
     54 
     55   // Returns true if the object should self-delete.
     56   bool Release() const;
     57 
     58  private:
     59   mutable AtomicRefCount ref_count_;
     60 #ifndef NDEBUG
     61   mutable bool in_dtor_;
     62 #endif
     63 
     64   DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafeBase);
     65 };
     66 
     67 }  // namespace subtle
     68 
     69 //
     70 // A base class for reference counted classes.  Otherwise, known as a cheap
     71 // knock-off of WebKit's RefCounted<T> class.  To use this guy just extend your
     72 // class from it like so:
     73 //
     74 //   class MyFoo : public base::RefCounted<MyFoo> {
     75 //    ...
     76 //    private:
     77 //     friend class base::RefCounted<MyFoo>;
     78 //     ~MyFoo();
     79 //   };
     80 //
     81 // You should always make your destructor private, to avoid any code deleting
     82 // the object accidently while there are references to it.
     83 template <class T>
     84 class RefCounted : public subtle::RefCountedBase {
     85  public:
     86   RefCounted() { }
     87   ~RefCounted() { }
     88 
     89   void AddRef() const {
     90     subtle::RefCountedBase::AddRef();
     91   }
     92 
     93   void Release() const {
     94     if (subtle::RefCountedBase::Release()) {
     95       delete static_cast<const T*>(this);
     96     }
     97   }
     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   ~RefCountedThreadSafe() { }
    136 
    137   void AddRef() const {
    138     subtle::RefCountedThreadSafeBase::AddRef();
    139   }
    140 
    141   void Release() const {
    142     if (subtle::RefCountedThreadSafeBase::Release()) {
    143       Traits::Destruct(static_cast<const T*>(this));
    144     }
    145   }
    146 
    147  private:
    148   friend struct DefaultRefCountedThreadSafeTraits<T>;
    149   static void DeleteInternal(const T* x) { delete x; }
    150 
    151   DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafe);
    152 };
    153 
    154 //
    155 // A wrapper for some piece of data so we can place other things in
    156 // scoped_refptrs<>.
    157 //
    158 template<typename T>
    159 class RefCountedData : public base::RefCounted< base::RefCountedData<T> > {
    160  public:
    161   RefCountedData() : data() {}
    162   RefCountedData(const T& in_value) : data(in_value) {}
    163 
    164   T data;
    165 };
    166 
    167 }  // namespace base
    168 
    169 //
    170 // A smart pointer class for reference counted objects.  Use this class instead
    171 // of calling AddRef and Release manually on a reference counted object to
    172 // avoid common memory leaks caused by forgetting to Release an object
    173 // reference.  Sample usage:
    174 //
    175 //   class MyFoo : public RefCounted<MyFoo> {
    176 //    ...
    177 //   };
    178 //
    179 //   void some_function() {
    180 //     scoped_refptr<MyFoo> foo = new MyFoo();
    181 //     foo->Method(param);
    182 //     // |foo| is released when this function returns
    183 //   }
    184 //
    185 //   void some_other_function() {
    186 //     scoped_refptr<MyFoo> foo = new MyFoo();
    187 //     ...
    188 //     foo = NULL;  // explicitly releases |foo|
    189 //     ...
    190 //     if (foo)
    191 //       foo->Method(param);
    192 //   }
    193 //
    194 // The above examples show how scoped_refptr<T> acts like a pointer to T.
    195 // Given two scoped_refptr<T> classes, it is also possible to exchange
    196 // references between the two objects, like so:
    197 //
    198 //   {
    199 //     scoped_refptr<MyFoo> a = new MyFoo();
    200 //     scoped_refptr<MyFoo> b;
    201 //
    202 //     b.swap(a);
    203 //     // now, |b| references the MyFoo object, and |a| references NULL.
    204 //   }
    205 //
    206 // To make both |a| and |b| in the above example reference the same MyFoo
    207 // object, simply use the assignment operator:
    208 //
    209 //   {
    210 //     scoped_refptr<MyFoo> a = new MyFoo();
    211 //     scoped_refptr<MyFoo> b;
    212 //
    213 //     b = a;
    214 //     // now, |a| and |b| each own a reference to the same MyFoo object.
    215 //   }
    216 //
    217 template <class T>
    218 class scoped_refptr {
    219  public:
    220   scoped_refptr() : ptr_(NULL) {
    221   }
    222 
    223   scoped_refptr(T* p) : ptr_(p) {
    224     if (ptr_)
    225       ptr_->AddRef();
    226   }
    227 
    228   scoped_refptr(const scoped_refptr<T>& r) : ptr_(r.ptr_) {
    229     if (ptr_)
    230       ptr_->AddRef();
    231   }
    232 
    233   template <typename U>
    234   scoped_refptr(const scoped_refptr<U>& r) : ptr_(r.get()) {
    235     if (ptr_)
    236       ptr_->AddRef();
    237   }
    238 
    239   ~scoped_refptr() {
    240     if (ptr_)
    241       ptr_->Release();
    242   }
    243 
    244   T* get() const { return ptr_; }
    245   operator T*() const { return ptr_; }
    246   T* operator->() const { return ptr_; }
    247 
    248   // Release a pointer.
    249   // The return value is the current pointer held by this object.
    250   // If this object holds a NULL pointer, the return value is NULL.
    251   // After this operation, this object will hold a NULL pointer,
    252   // and will not own the object any more.
    253   T* release() {
    254     T* retVal = ptr_;
    255     ptr_ = NULL;
    256     return retVal;
    257   }
    258 
    259   scoped_refptr<T>& operator=(T* p) {
    260     // AddRef first so that self assignment should work
    261     if (p)
    262       p->AddRef();
    263     T* old_ptr = ptr_;
    264     ptr_ = p;
    265     if (old_ptr)
    266       old_ptr ->Release();
    267     return *this;
    268   }
    269 
    270   scoped_refptr<T>& operator=(const scoped_refptr<T>& r) {
    271     return *this = r.ptr_;
    272   }
    273 
    274   template <typename U>
    275   scoped_refptr<T>& operator=(const scoped_refptr<U>& r) {
    276     return *this = r.get();
    277   }
    278 
    279   void swap(T** pp) {
    280     T* p = ptr_;
    281     ptr_ = *pp;
    282     *pp = p;
    283   }
    284 
    285   void swap(scoped_refptr<T>& r) {
    286     swap(&r.ptr_);
    287   }
    288 
    289  protected:
    290   T* ptr_;
    291 };
    292 
    293 // Handy utility for creating a scoped_refptr<T> out of a T* explicitly without
    294 // having to retype all the template arguments
    295 template <typename T>
    296 scoped_refptr<T> make_scoped_refptr(T* t) {
    297   return scoped_refptr<T>(t);
    298 }
    299 
    300 #endif  // BASE_MEMORY_REF_COUNTED_H_
    301