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.
5 #ifndef BASE_MEMORY_REF_COUNTED_H_
6 #define BASE_MEMORY_REF_COUNTED_H_
11 #include "base/atomic_ref_count.h"
12 #include "base/base_export.h"
13 #include "base/compiler_specific.h"
15 #include "base/logging.h"
17 #include "base/threading/thread_collision_warner.h"
18 #include "build/build_config.h"
20 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
21 #define DISABLE_SCOPED_REFPTR_CONVERSION_OPERATOR
28 class BASE_EXPORT RefCountedBase
{
30 bool HasOneRef() const { return ref_count_
== 1; }
43 DCHECK(in_dtor_
) << "RefCounted object deleted without calling Release()";
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_);
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_);
68 if (--ref_count_
== 0) {
78 mutable int ref_count_
;
80 mutable bool in_dtor_
;
83 DFAKE_MUTEX(add_release_
);
85 DISALLOW_COPY_AND_ASSIGN(RefCountedBase
);
88 class BASE_EXPORT RefCountedThreadSafeBase
{
90 bool HasOneRef() const;
93 RefCountedThreadSafeBase();
94 ~RefCountedThreadSafeBase();
98 // Returns true if the object should self-delete.
102 mutable AtomicRefCount ref_count_
;
104 mutable bool in_dtor_
;
107 DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafeBase
);
110 } // namespace subtle
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:
117 // class MyFoo : public base::RefCounted<MyFoo> {
120 // friend class base::RefCounted<MyFoo>;
124 // You should always make your destructor private, to avoid any code deleting
125 // the object accidently while there are references to it.
127 class RefCounted
: public subtle::RefCountedBase
{
131 void AddRef() const {
132 subtle::RefCountedBase::AddRef();
135 void Release() const {
136 if (subtle::RefCountedBase::Release()) {
137 delete static_cast<const T
*>(this);
145 DISALLOW_COPY_AND_ASSIGN(RefCounted
<T
>);
148 // Forward declaration.
149 template <class T
, typename Traits
> class RefCountedThreadSafe
;
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.
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
);
165 // A thread-safe variant of RefCounted<T>
167 // class MyFoo : public base::RefCountedThreadSafe<MyFoo> {
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.
174 // friend class base::RefCountedThreadSafe<MyFoo>;
176 template <class T
, typename Traits
= DefaultRefCountedThreadSafeTraits
<T
> >
177 class RefCountedThreadSafe
: public subtle::RefCountedThreadSafeBase
{
179 RefCountedThreadSafe() {}
181 void AddRef() const {
182 subtle::RefCountedThreadSafeBase::AddRef();
185 void Release() const {
186 if (subtle::RefCountedThreadSafeBase::Release()) {
187 Traits::Destruct(static_cast<const T
*>(this));
192 ~RefCountedThreadSafe() {}
195 friend struct DefaultRefCountedThreadSafeTraits
<T
>;
196 static void DeleteInternal(const T
* x
) { delete x
; }
198 DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafe
);
202 // A thread-safe wrapper for some piece of data so we can place other
203 // things in scoped_refptrs<>.
207 : public base::RefCountedThreadSafe
< base::RefCountedData
<T
> > {
209 RefCountedData() : data() {}
210 RefCountedData(const T
& in_value
) : data(in_value
) {}
215 friend class base::RefCountedThreadSafe
<base::RefCountedData
<T
> >;
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:
227 // class MyFoo : public RefCounted<MyFoo> {
231 // void some_function() {
232 // scoped_refptr<MyFoo> foo = new MyFoo();
233 // foo->Method(param);
234 // // |foo| is released when this function returns
237 // void some_other_function() {
238 // scoped_refptr<MyFoo> foo = new MyFoo();
240 // foo = NULL; // explicitly releases |foo|
243 // foo->Method(param);
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:
251 // scoped_refptr<MyFoo> a = new MyFoo();
252 // scoped_refptr<MyFoo> b;
255 // // now, |b| references the MyFoo object, and |a| references NULL.
258 // To make both |a| and |b| in the above example reference the same MyFoo
259 // object, simply use the assignment operator:
262 // scoped_refptr<MyFoo> a = new MyFoo();
263 // scoped_refptr<MyFoo> b;
266 // // now, |a| and |b| each own a reference to the same MyFoo object.
270 class scoped_refptr
{
272 typedef T element_type
;
274 scoped_refptr() : ptr_(NULL
) {
277 scoped_refptr(T
* p
) : ptr_(p
) {
282 scoped_refptr(const scoped_refptr
<T
>& r
) : ptr_(r
.ptr_
) {
287 template <typename U
>
288 scoped_refptr(const scoped_refptr
<U
>& r
) : ptr_(r
.get()) {
298 T
* get() const { return ptr_
; }
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_
; }
306 T
& operator*() const {
307 assert(ptr_
!= NULL
);
311 T
* operator->() const {
312 assert(ptr_
!= NULL
);
316 scoped_refptr
<T
>& operator=(T
* p
) {
317 // AddRef first so that self assignment should work
327 scoped_refptr
<T
>& operator=(const scoped_refptr
<T
>& r
) {
328 return *this = r
.ptr_
;
331 template <typename U
>
332 scoped_refptr
<T
>& operator=(const scoped_refptr
<U
>& r
) {
333 return *this = r
.get();
342 void swap(scoped_refptr
<T
>& r
) {
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();
352 template <typename U
>
353 bool operator!=(const scoped_refptr
<U
>& rhs
) const {
354 return !operator==(rhs
);
357 template <typename U
>
358 bool operator<(const scoped_refptr
<U
>& rhs
) const {
359 return ptr_
< rhs
.get();
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
);
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
;
381 template <typename T
, typename U
>
382 bool operator==(const T
* lhs
, const scoped_refptr
<U
>& rhs
) {
383 return lhs
== rhs
.get();
386 template <typename T
, typename U
>
387 bool operator!=(const scoped_refptr
<T
>& lhs
, const U
* rhs
) {
388 return !operator==(lhs
, rhs
);
391 template <typename T
, typename U
>
392 bool operator!=(const T
* lhs
, const scoped_refptr
<U
>& rhs
) {
393 return !operator==(lhs
, rhs
);
396 template <typename T
>
397 std::ostream
& operator<<(std::ostream
& out
, const scoped_refptr
<T
>& p
) {
398 return out
<< p
.get();
400 #endif // defined(DISABLE_SCOPED_REFPTR_CONVERSION_OPERATOR)
402 #endif // BASE_MEMORY_REF_COUNTED_H_