• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
HasOneRef()30   bool HasOneRef() const { return ref_count_ == 1; }
31 
32  protected:
RefCountedBase()33   RefCountedBase()
34       : ref_count_(0)
35   #ifndef NDEBUG
36       , in_dtor_(false)
37   #endif
38       {
39   }
40 
~RefCountedBase()41   ~RefCountedBase() {
42   #ifndef NDEBUG
43     DCHECK(in_dtor_) << "RefCounted object deleted without calling Release()";
44   #endif
45   }
46 
47 
AddRef()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.
Release()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:
RefCounted()129   RefCounted() {}
130 
AddRef()131   void AddRef() const {
132     subtle::RefCountedBase::AddRef();
133   }
134 
Release()135   void Release() const {
136     if (subtle::RefCountedBase::Release()) {
137       delete static_cast<const T*>(this);
138     }
139   }
140 
141  protected:
~RefCounted()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 {
DestructDefaultRefCountedThreadSafeTraits155   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:
RefCountedThreadSafe()179   RefCountedThreadSafe() {}
180 
AddRef()181   void AddRef() const {
182     subtle::RefCountedThreadSafeBase::AddRef();
183   }
184 
Release()185   void Release() const {
186     if (subtle::RefCountedThreadSafeBase::Release()) {
187       Traits::Destruct(static_cast<const T*>(this));
188     }
189   }
190 
191  protected:
~RefCountedThreadSafe()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