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/move.h"
18 #include "base/threading/thread_collision_warner.h"
19 #include "build/build_config.h"
25 class BASE_EXPORT RefCountedBase
{
27 bool HasOneRef() const { return ref_count_
== 1; }
40 DCHECK(in_dtor_
) << "RefCounted object deleted without calling Release()";
46 // TODO(maruel): Add back once it doesn't assert 500 times/sec.
47 // Current thread books the critical section "AddRelease"
48 // without release it.
49 // DFAKE_SCOPED_LOCK_THREAD_LOCKED(add_release_);
56 // Returns true if the object should self-delete.
57 bool Release() const {
58 // TODO(maruel): Add back once it doesn't assert 500 times/sec.
59 // Current thread books the critical section "AddRelease"
60 // without release it.
61 // DFAKE_SCOPED_LOCK_THREAD_LOCKED(add_release_);
65 if (--ref_count_
== 0) {
75 mutable int ref_count_
;
77 mutable bool in_dtor_
;
80 DFAKE_MUTEX(add_release_
);
82 DISALLOW_COPY_AND_ASSIGN(RefCountedBase
);
85 class BASE_EXPORT RefCountedThreadSafeBase
{
87 bool HasOneRef() const;
90 RefCountedThreadSafeBase();
91 ~RefCountedThreadSafeBase();
95 // Returns true if the object should self-delete.
99 mutable AtomicRefCount ref_count_
;
101 mutable bool in_dtor_
;
104 DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafeBase
);
107 } // namespace subtle
110 // A base class for reference counted classes. Otherwise, known as a cheap
111 // knock-off of WebKit's RefCounted<T> class. To use this guy just extend your
112 // class from it like so:
114 // class MyFoo : public base::RefCounted<MyFoo> {
117 // friend class base::RefCounted<MyFoo>;
121 // You should always make your destructor private, to avoid any code deleting
122 // the object accidently while there are references to it.
124 class RefCounted
: public subtle::RefCountedBase
{
128 void AddRef() const {
129 subtle::RefCountedBase::AddRef();
132 void Release() const {
133 if (subtle::RefCountedBase::Release()) {
134 delete static_cast<const T
*>(this);
142 DISALLOW_COPY_AND_ASSIGN(RefCounted
<T
>);
145 // Forward declaration.
146 template <class T
, typename Traits
> class RefCountedThreadSafe
;
148 // Default traits for RefCountedThreadSafe<T>. Deletes the object when its ref
149 // count reaches 0. Overload to delete it on a different thread etc.
151 struct DefaultRefCountedThreadSafeTraits
{
152 static void Destruct(const T
* x
) {
153 // Delete through RefCountedThreadSafe to make child classes only need to be
154 // friend with RefCountedThreadSafe instead of this struct, which is an
155 // implementation detail.
156 RefCountedThreadSafe
<T
,
157 DefaultRefCountedThreadSafeTraits
>::DeleteInternal(x
);
162 // A thread-safe variant of RefCounted<T>
164 // class MyFoo : public base::RefCountedThreadSafe<MyFoo> {
168 // If you're using the default trait, then you should add compile time
169 // asserts that no one else is deleting your object. i.e.
171 // friend class base::RefCountedThreadSafe<MyFoo>;
173 template <class T
, typename Traits
= DefaultRefCountedThreadSafeTraits
<T
> >
174 class RefCountedThreadSafe
: public subtle::RefCountedThreadSafeBase
{
176 RefCountedThreadSafe() {}
178 void AddRef() const {
179 subtle::RefCountedThreadSafeBase::AddRef();
182 void Release() const {
183 if (subtle::RefCountedThreadSafeBase::Release()) {
184 Traits::Destruct(static_cast<const T
*>(this));
189 ~RefCountedThreadSafe() {}
192 friend struct DefaultRefCountedThreadSafeTraits
<T
>;
193 static void DeleteInternal(const T
* x
) { delete x
; }
195 DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafe
);
199 // A thread-safe wrapper for some piece of data so we can place other
200 // things in scoped_refptrs<>.
204 : public base::RefCountedThreadSafe
< base::RefCountedData
<T
> > {
206 RefCountedData() : data() {}
207 RefCountedData(const T
& in_value
) : data(in_value
) {}
212 friend class base::RefCountedThreadSafe
<base::RefCountedData
<T
> >;
219 // A smart pointer class for reference counted objects. Use this class instead
220 // of calling AddRef and Release manually on a reference counted object to
221 // avoid common memory leaks caused by forgetting to Release an object
222 // reference. Sample usage:
224 // class MyFoo : public RefCounted<MyFoo> {
228 // void some_function() {
229 // scoped_refptr<MyFoo> foo = new MyFoo();
230 // foo->Method(param);
231 // // |foo| is released when this function returns
234 // void some_other_function() {
235 // scoped_refptr<MyFoo> foo = new MyFoo();
237 // foo = NULL; // explicitly releases |foo|
240 // foo->Method(param);
243 // The above examples show how scoped_refptr<T> acts like a pointer to T.
244 // Given two scoped_refptr<T> classes, it is also possible to exchange
245 // references between the two objects, like so:
248 // scoped_refptr<MyFoo> a = new MyFoo();
249 // scoped_refptr<MyFoo> b;
252 // // now, |b| references the MyFoo object, and |a| references NULL.
255 // To make both |a| and |b| in the above example reference the same MyFoo
256 // object, simply use the assignment operator:
259 // scoped_refptr<MyFoo> a = new MyFoo();
260 // scoped_refptr<MyFoo> b;
263 // // now, |a| and |b| each own a reference to the same MyFoo object.
267 class scoped_refptr
{
268 TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(scoped_refptr
)
270 typedef T element_type
;
272 scoped_refptr() : ptr_(NULL
) {
275 scoped_refptr(T
* p
) : ptr_(p
) {
280 scoped_refptr(const scoped_refptr
<T
>& r
) : ptr_(r
.ptr_
) {
285 template <typename U
>
286 scoped_refptr(const scoped_refptr
<U
>& r
) : ptr_(r
.get()) {
291 template <typename U
>
292 scoped_refptr(scoped_refptr
<U
>&& r
) : ptr_(r
.get()) {
301 T
* get() const { return ptr_
; }
303 T
& operator*() const {
304 assert(ptr_
!= NULL
);
308 T
* operator->() const {
309 assert(ptr_
!= NULL
);
313 scoped_refptr
<T
>& operator=(T
* p
) {
314 // AddRef first so that self assignment should work
324 scoped_refptr
<T
>& operator=(const scoped_refptr
<T
>& r
) {
325 return *this = r
.ptr_
;
328 template <typename U
>
329 scoped_refptr
<T
>& operator=(const scoped_refptr
<U
>& r
) {
330 return *this = r
.get();
333 scoped_refptr
<T
>& operator=(scoped_refptr
<T
>&& r
) {
334 scoped_refptr
<T
>(r
.Pass()).swap(*this);
338 template <typename U
>
339 scoped_refptr
<T
>& operator=(scoped_refptr
<U
>&& r
) {
340 scoped_refptr
<T
>(r
.Pass()).swap(*this);
350 void swap(scoped_refptr
<T
>& r
) {
355 template <typename U
> friend class scoped_refptr
;
357 // Allow scoped_refptr<T> to be used in boolean expressions, but not
358 // implicitly convertible to a real bool (which is dangerous).
360 // Note that this trick is only safe when the == and != operators
361 // are declared explicitly, as otherwise "refptr1 == refptr2"
362 // will compile but do the wrong thing (i.e., convert to Testable
363 // and then do the comparison).
364 typedef T
* scoped_refptr::*Testable
;
367 operator Testable() const { return ptr_
? &scoped_refptr::ptr_
: nullptr; }
369 template <typename U
>
370 bool operator==(const scoped_refptr
<U
>& rhs
) const {
371 return ptr_
== rhs
.get();
374 template <typename U
>
375 bool operator!=(const scoped_refptr
<U
>& rhs
) const {
376 return !operator==(rhs
);
379 template <typename U
>
380 bool operator<(const scoped_refptr
<U
>& rhs
) const {
381 return ptr_
< rhs
.get();
388 // Non-inline helpers to allow:
390 // extern template class scoped_refptr<Opaque>;
391 // Otherwise the compiler will complain that Opaque is an incomplete type.
392 static void AddRef(T
* ptr
);
393 static void Release(T
* ptr
);
396 template <typename T
>
397 void scoped_refptr
<T
>::AddRef(T
* ptr
) {
401 template <typename T
>
402 void scoped_refptr
<T
>::Release(T
* ptr
) {
406 // Handy utility for creating a scoped_refptr<T> out of a T* explicitly without
407 // having to retype all the template arguments
408 template <typename T
>
409 scoped_refptr
<T
> make_scoped_refptr(T
* t
) {
410 return scoped_refptr
<T
>(t
);
413 // Temporary operator overloads to facilitate the transition. See
414 // https://crbug.com/110610.
415 template <typename T
, typename U
>
416 bool operator==(const scoped_refptr
<T
>& lhs
, const U
* rhs
) {
417 return lhs
.get() == rhs
;
420 template <typename T
, typename U
>
421 bool operator==(const T
* lhs
, const scoped_refptr
<U
>& rhs
) {
422 return lhs
== rhs
.get();
425 template <typename T
, typename U
>
426 bool operator!=(const scoped_refptr
<T
>& lhs
, const U
* rhs
) {
427 return !operator==(lhs
, rhs
);
430 template <typename T
, typename U
>
431 bool operator!=(const T
* lhs
, const scoped_refptr
<U
>& rhs
) {
432 return !operator==(lhs
, rhs
);
435 template <typename T
>
436 std::ostream
& operator<<(std::ostream
& out
, const scoped_refptr
<T
>& p
) {
437 return out
<< p
.get();
440 #endif // BASE_MEMORY_REF_COUNTED_H_