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 #include <iosfwd>
     10 
     11 #include "base/atomic_ref_count.h"
     12 #include "base/base_export.h"
     13 #include "base/compiler_specific.h"
     14 #ifndef NDEBUG
     15 #include "base/logging.h"
     16 #endif
     17 #include "base/threading/thread_collision_warner.h"
     18 #include "build/build_config.h"
     19 
     20 #if defined(OS_LINUX) || (defined(OS_MACOSX) && !defined(OS_IOS))
     21 #define DISABLE_SCOPED_REFPTR_CONVERSION_OPERATOR
     22 #endif
     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 guy 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 private, 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       ptr_->AddRef();
    280   }
    281 
    282   scoped_refptr(const scoped_refptr<T>& r) : ptr_(r.ptr_) {
    283     if (ptr_)
    284       ptr_->AddRef();
    285   }
    286 
    287   template <typename U>
    288   scoped_refptr(const scoped_refptr<U>& r) : ptr_(r.get()) {
    289     if (ptr_)
    290       ptr_->AddRef();
    291   }
    292 
    293   ~scoped_refptr() {
    294     if (ptr_)
    295       ptr_->Release();
    296   }
    297 
    298   T* get() const { return ptr_; }
    299 
    300 #if !defined(DISABLE_SCOPED_REFPTR_CONVERSION_OPERATOR)
    301   // Allow scoped_refptr<C> to be used in boolean expression
    302   // and comparison operations.
    303   operator T*() const { return ptr_; }
    304 #endif
    305 
    306   T& operator*() const {
    307     assert(ptr_ != NULL);
    308     return *ptr_;
    309   }
    310 
    311   T* operator->() const {
    312     assert(ptr_ != NULL);
    313     return ptr_;
    314   }
    315 
    316   scoped_refptr<T>& operator=(T* p) {
    317     // AddRef first so that self assignment should work
    318     if (p)
    319       p->AddRef();
    320     T* old_ptr = ptr_;
    321     ptr_ = p;
    322     if (old_ptr)
    323       old_ptr->Release();
    324     return *this;
    325   }
    326 
    327   scoped_refptr<T>& operator=(const scoped_refptr<T>& r) {
    328     return *this = r.ptr_;
    329   }
    330 
    331   template <typename U>
    332   scoped_refptr<T>& operator=(const scoped_refptr<U>& r) {
    333     return *this = r.get();
    334   }
    335 
    336   void swap(T** pp) {
    337     T* p = ptr_;
    338     ptr_ = *pp;
    339     *pp = p;
    340   }
    341 
    342   void swap(scoped_refptr<T>& r) {
    343     swap(&r.ptr_);
    344   }
    345 
    346 #if defined(DISABLE_SCOPED_REFPTR_CONVERSION_OPERATOR)
    347   template <typename U>
    348   bool operator==(const scoped_refptr<U>& rhs) const {
    349     return ptr_ == rhs.get();
    350   }
    351 
    352   template <typename U>
    353   bool operator!=(const scoped_refptr<U>& rhs) const {
    354     return !operator==(rhs);
    355   }
    356 
    357   template <typename U>
    358   bool operator<(const scoped_refptr<U>& rhs) const {
    359     return ptr_ < rhs.get();
    360   }
    361 #endif
    362 
    363  protected:
    364   T* ptr_;
    365 };
    366 
    367 // Handy utility for creating a scoped_refptr<T> out of a T* explicitly without
    368 // having to retype all the template arguments
    369 template <typename T>
    370 scoped_refptr<T> make_scoped_refptr(T* t) {
    371   return scoped_refptr<T>(t);
    372 }
    373 
    374 #if defined(DISABLE_SCOPED_REFPTR_CONVERSION_OPERATOR)
    375 // Temporary operator overloads to facilitate the transition...
    376 template <typename T, typename U>
    377 bool operator==(const scoped_refptr<T>& lhs, const U* rhs) {
    378   return lhs.get() == rhs;
    379 }
    380 
    381 template <typename T, typename U>
    382 bool operator==(const T* lhs, const scoped_refptr<U>& rhs) {
    383   return lhs == rhs.get();
    384 }
    385 
    386 template <typename T, typename U>
    387 bool operator!=(const scoped_refptr<T>& lhs, const U* rhs) {
    388   return !operator==(lhs, rhs);
    389 }
    390 
    391 template <typename T, typename U>
    392 bool operator!=(const T* lhs, const scoped_refptr<U>& rhs) {
    393   return !operator==(lhs, rhs);
    394 }
    395 
    396 template <typename T>
    397 std::ostream& operator<<(std::ostream& out, const scoped_refptr<T>& p) {
    398   return out << p.get();
    399 }
    400 #endif  // defined(DISABLE_SCOPED_REFPTR_CONVERSION_OPERATOR)
    401 
    402 #endif  // BASE_MEMORY_REF_COUNTED_H_
    403