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 <stddef.h>
9 
10 #include <cassert>
11 #include <iosfwd>
12 #include <type_traits>
13 
14 #include "base/atomic_ref_count.h"
15 #include "base/base_export.h"
16 #include "base/compiler_specific.h"
17 #include "base/macros.h"
18 #ifndef NDEBUG
19 #include "base/logging.h"
20 #endif
21 #include "base/threading/thread_collision_warner.h"
22 #include "build/build_config.h"
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, 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 non-public, 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       AddRef(ptr_);
280   }
281 
282   // Copy constructor.
283   scoped_refptr(const scoped_refptr<T>& r) : ptr_(r.ptr_) {
284     if (ptr_)
285       AddRef(ptr_);
286   }
287 
288   // Copy conversion constructor.
289   template <typename U,
290             typename = typename std::enable_if<
291                 std::is_convertible<U*, T*>::value>::type>
292   scoped_refptr(const scoped_refptr<U>& r) : ptr_(r.get()) {
293     if (ptr_)
294       AddRef(ptr_);
295   }
296 
297   // Move constructor. This is required in addition to the conversion
298   // constructor below in order for clang to warn about pessimizing moves.
299   scoped_refptr(scoped_refptr&& r) : ptr_(r.get()) { r.ptr_ = nullptr; }
300 
301   // Move conversion constructor.
302   template <typename U,
303             typename = typename std::enable_if<
304                 std::is_convertible<U*, T*>::value>::type>
305   scoped_refptr(scoped_refptr<U>&& r) : ptr_(r.get()) {
306     r.ptr_ = nullptr;
307   }
308 
309   ~scoped_refptr() {
310     if (ptr_)
311       Release(ptr_);
312   }
313 
314   T* get() const { return ptr_; }
315 
316   T& operator*() const {
317     assert(ptr_ != NULL);
318     return *ptr_;
319   }
320 
321   T* operator->() const {
322     assert(ptr_ != NULL);
323     return ptr_;
324   }
325 
326   scoped_refptr<T>& operator=(T* p) {
327     // AddRef first so that self assignment should work
328     if (p)
329       AddRef(p);
330     T* old_ptr = ptr_;
331     ptr_ = p;
332     if (old_ptr)
333       Release(old_ptr);
334     return *this;
335   }
336 
337   scoped_refptr<T>& operator=(const scoped_refptr<T>& r) {
338     return *this = r.ptr_;
339   }
340 
341   template <typename U>
342   scoped_refptr<T>& operator=(const scoped_refptr<U>& r) {
343     return *this = r.get();
344   }
345 
346   scoped_refptr<T>& operator=(scoped_refptr<T>&& r) {
347     scoped_refptr<T>(std::move(r)).swap(*this);
348     return *this;
349   }
350 
351   template <typename U>
352   scoped_refptr<T>& operator=(scoped_refptr<U>&& r) {
353     scoped_refptr<T>(std::move(r)).swap(*this);
354     return *this;
355   }
356 
357   void swap(T** pp) {
358     T* p = ptr_;
359     ptr_ = *pp;
360     *pp = p;
361   }
362 
363   void swap(scoped_refptr<T>& r) {
364     swap(&r.ptr_);
365   }
366 
367   explicit operator bool() const { return ptr_ != nullptr; }
368 
369   template <typename U>
370   bool operator==(const scoped_refptr<U>& rhs) const {
371     return ptr_ == rhs.get();
372   }
373 
374   template <typename U>
375   bool operator!=(const scoped_refptr<U>& rhs) const {
376     return !operator==(rhs);
377   }
378 
379   template <typename U>
380   bool operator<(const scoped_refptr<U>& rhs) const {
381     return ptr_ < rhs.get();
382   }
383 
384  protected:
385   T* ptr_;
386 
387  private:
388   // Friend required for move constructors that set r.ptr_ to null.
389   template <typename U>
390   friend class scoped_refptr;
391 
392   // Non-inline helpers to allow:
393   //     class Opaque;
394   //     extern template class scoped_refptr<Opaque>;
395   // Otherwise the compiler will complain that Opaque is an incomplete type.
396   static void AddRef(T* ptr);
397   static void Release(T* ptr);
398 };
399 
400 template <typename T>
401 void scoped_refptr<T>::AddRef(T* ptr) {
402   ptr->AddRef();
403 }
404 
405 template <typename T>
406 void scoped_refptr<T>::Release(T* ptr) {
407   ptr->Release();
408 }
409 
410 // Handy utility for creating a scoped_refptr<T> out of a T* explicitly without
411 // having to retype all the template arguments
412 template <typename T>
413 scoped_refptr<T> make_scoped_refptr(T* t) {
414   return scoped_refptr<T>(t);
415 }
416 
417 template <typename T, typename U>
418 bool operator==(const scoped_refptr<T>& lhs, const U* rhs) {
419   return lhs.get() == rhs;
420 }
421 
422 template <typename T, typename U>
423 bool operator==(const T* lhs, const scoped_refptr<U>& rhs) {
424   return lhs == rhs.get();
425 }
426 
427 template <typename T>
428 bool operator==(const scoped_refptr<T>& lhs, std::nullptr_t) {
429   return !static_cast<bool>(lhs);
430 }
431 
432 template <typename T>
433 bool operator==(std::nullptr_t, const scoped_refptr<T>& rhs) {
434   return !static_cast<bool>(rhs);
435 }
436 
437 template <typename T, typename U>
438 bool operator!=(const scoped_refptr<T>& lhs, const U* rhs) {
439   return !operator==(lhs, rhs);
440 }
441 
442 template <typename T, typename U>
443 bool operator!=(const T* lhs, const scoped_refptr<U>& rhs) {
444   return !operator==(lhs, rhs);
445 }
446 
447 template <typename T>
448 bool operator!=(const scoped_refptr<T>& lhs, std::nullptr_t null) {
449   return !operator==(lhs, null);
450 }
451 
452 template <typename T>
453 bool operator!=(std::nullptr_t null, const scoped_refptr<T>& rhs) {
454   return !operator==(null, rhs);
455 }
456 
457 template <typename T>
458 std::ostream& operator<<(std::ostream& out, const scoped_refptr<T>& p) {
459   return out << p.get();
460 }
461 
462 #endif  // BASE_MEMORY_REF_COUNTED_H_
463