blob: be5eda8e0839cfb15b77fc5ae99bfaac4ae11f45 [file] [log] [blame]
mnaganov@chromium.org08a60f52012-01-05 19:52:55 +09001// Copyright (c) 2012 The Chromium Authors. All rights reserved.
levin@chromium.org5c528682011-03-28 10:54:15 +09002// 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_
levin@chromium.org5c528682011-03-28 10:54:15 +09007
akalin@chromium.orgee0b43d2012-01-31 11:16:55 +09008#include <cassert>
9
levin@chromium.org5c528682011-03-28 10:54:15 +090010#include "base/atomic_ref_count.h"
darin@chromium.orge585bed2011-08-06 00:34:00 +090011#include "base/base_export.h"
xiaomings@google.comb5c3d672012-08-29 05:19:51 +090012#include "base/compiler_specific.h"
mikhail.pozdnyakov@intel.comd45f3e32013-12-20 05:48:41 +090013#ifndef NDEBUG
14#include "base/logging.h"
15#endif
levin@chromium.org5c528682011-03-28 10:54:15 +090016#include "base/threading/thread_collision_warner.h"
17
18namespace base {
19
20namespace subtle {
21
darin@chromium.orge585bed2011-08-06 00:34:00 +090022class BASE_EXPORT RefCountedBase {
levin@chromium.org5c528682011-03-28 10:54:15 +090023 public:
levin@chromium.org5c528682011-03-28 10:54:15 +090024 bool HasOneRef() const { return ref_count_ == 1; }
25
26 protected:
mikhail.pozdnyakov@intel.comd45f3e32013-12-20 05:48:41 +090027 RefCountedBase()
28 : ref_count_(0)
29 #ifndef NDEBUG
30 , in_dtor_(false)
31 #endif
32 {
33 }
levin@chromium.org5c528682011-03-28 10:54:15 +090034
mikhail.pozdnyakov@intel.comd45f3e32013-12-20 05:48:41 +090035 ~RefCountedBase() {
36 #ifndef NDEBUG
37 DCHECK(in_dtor_) << "RefCounted object deleted without calling Release()";
38 #endif
39 }
40
41
42 void AddRef() const {
43 // TODO(maruel): Add back once it doesn't assert 500 times/sec.
44 // Current thread books the critical section "AddRelease"
45 // without release it.
46 // DFAKE_SCOPED_LOCK_THREAD_LOCKED(add_release_);
47 #ifndef NDEBUG
48 DCHECK(!in_dtor_);
49 #endif
50 ++ref_count_;
51 }
levin@chromium.org5c528682011-03-28 10:54:15 +090052
53 // Returns true if the object should self-delete.
mikhail.pozdnyakov@intel.comd45f3e32013-12-20 05:48:41 +090054 bool Release() const {
55 // TODO(maruel): Add back once it doesn't assert 500 times/sec.
56 // Current thread books the critical section "AddRelease"
57 // without release it.
58 // DFAKE_SCOPED_LOCK_THREAD_LOCKED(add_release_);
59 #ifndef NDEBUG
60 DCHECK(!in_dtor_);
61 #endif
62 if (--ref_count_ == 0) {
63 #ifndef NDEBUG
64 in_dtor_ = true;
65 #endif
66 return true;
67 }
68 return false;
69 }
levin@chromium.org5c528682011-03-28 10:54:15 +090070
71 private:
72 mutable int ref_count_;
73#ifndef NDEBUG
74 mutable bool in_dtor_;
75#endif
76
77 DFAKE_MUTEX(add_release_);
78
79 DISALLOW_COPY_AND_ASSIGN(RefCountedBase);
80};
81
darin@chromium.orge585bed2011-08-06 00:34:00 +090082class BASE_EXPORT RefCountedThreadSafeBase {
levin@chromium.org5c528682011-03-28 10:54:15 +090083 public:
levin@chromium.org5c528682011-03-28 10:54:15 +090084 bool HasOneRef() const;
85
86 protected:
87 RefCountedThreadSafeBase();
88 ~RefCountedThreadSafeBase();
89
90 void AddRef() const;
91
92 // Returns true if the object should self-delete.
93 bool Release() const;
94
95 private:
96 mutable AtomicRefCount ref_count_;
97#ifndef NDEBUG
98 mutable bool in_dtor_;
99#endif
100
101 DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafeBase);
102};
103
104} // namespace subtle
105
106//
107// A base class for reference counted classes. Otherwise, known as a cheap
108// knock-off of WebKit's RefCounted<T> class. To use this guy just extend your
109// class from it like so:
110//
111// class MyFoo : public base::RefCounted<MyFoo> {
112// ...
113// private:
114// friend class base::RefCounted<MyFoo>;
115// ~MyFoo();
116// };
117//
118// You should always make your destructor private, to avoid any code deleting
119// the object accidently while there are references to it.
120template <class T>
121class RefCounted : public subtle::RefCountedBase {
122 public:
rsleevi@chromium.orgd55e9a42012-06-26 15:23:00 +0900123 RefCounted() {}
levin@chromium.org5c528682011-03-28 10:54:15 +0900124
125 void AddRef() const {
126 subtle::RefCountedBase::AddRef();
127 }
128
129 void Release() const {
130 if (subtle::RefCountedBase::Release()) {
131 delete static_cast<const T*>(this);
132 }
133 }
134
rsleevi@chromium.orgd55e9a42012-06-26 15:23:00 +0900135 protected:
136 ~RefCounted() {}
137
levin@chromium.org5c528682011-03-28 10:54:15 +0900138 private:
139 DISALLOW_COPY_AND_ASSIGN(RefCounted<T>);
140};
141
142// Forward declaration.
143template <class T, typename Traits> class RefCountedThreadSafe;
144
145// Default traits for RefCountedThreadSafe<T>. Deletes the object when its ref
146// count reaches 0. Overload to delete it on a different thread etc.
147template<typename T>
148struct DefaultRefCountedThreadSafeTraits {
149 static void Destruct(const T* x) {
150 // Delete through RefCountedThreadSafe to make child classes only need to be
151 // friend with RefCountedThreadSafe instead of this struct, which is an
152 // implementation detail.
153 RefCountedThreadSafe<T,
154 DefaultRefCountedThreadSafeTraits>::DeleteInternal(x);
155 }
156};
157
158//
159// A thread-safe variant of RefCounted<T>
160//
161// class MyFoo : public base::RefCountedThreadSafe<MyFoo> {
162// ...
163// };
164//
165// If you're using the default trait, then you should add compile time
166// asserts that no one else is deleting your object. i.e.
167// private:
168// friend class base::RefCountedThreadSafe<MyFoo>;
169// ~MyFoo();
170template <class T, typename Traits = DefaultRefCountedThreadSafeTraits<T> >
171class RefCountedThreadSafe : public subtle::RefCountedThreadSafeBase {
172 public:
rsleevi@chromium.orgd55e9a42012-06-26 15:23:00 +0900173 RefCountedThreadSafe() {}
levin@chromium.org5c528682011-03-28 10:54:15 +0900174
175 void AddRef() const {
176 subtle::RefCountedThreadSafeBase::AddRef();
177 }
178
179 void Release() const {
180 if (subtle::RefCountedThreadSafeBase::Release()) {
181 Traits::Destruct(static_cast<const T*>(this));
182 }
183 }
184
rsleevi@chromium.orgd55e9a42012-06-26 15:23:00 +0900185 protected:
186 ~RefCountedThreadSafe() {}
187
levin@chromium.org5c528682011-03-28 10:54:15 +0900188 private:
189 friend struct DefaultRefCountedThreadSafeTraits<T>;
190 static void DeleteInternal(const T* x) { delete x; }
191
192 DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafe);
193};
194
195//
akalin@chromium.org4c0f0602012-11-14 19:05:22 +0900196// A thread-safe wrapper for some piece of data so we can place other
197// things in scoped_refptrs<>.
levin@chromium.org5c528682011-03-28 10:54:15 +0900198//
199template<typename T>
akalin@chromium.org4c0f0602012-11-14 19:05:22 +0900200class RefCountedData
201 : public base::RefCountedThreadSafe< base::RefCountedData<T> > {
levin@chromium.org5c528682011-03-28 10:54:15 +0900202 public:
203 RefCountedData() : data() {}
204 RefCountedData(const T& in_value) : data(in_value) {}
205
206 T data;
rsleevi@chromium.org3c3d9372012-06-25 17:15:42 +0900207
208 private:
akalin@chromium.org4c0f0602012-11-14 19:05:22 +0900209 friend class base::RefCountedThreadSafe<base::RefCountedData<T> >;
rsleevi@chromium.org3c3d9372012-06-25 17:15:42 +0900210 ~RefCountedData() {}
levin@chromium.org5c528682011-03-28 10:54:15 +0900211};
212
213} // namespace base
214
215//
216// A smart pointer class for reference counted objects. Use this class instead
217// of calling AddRef and Release manually on a reference counted object to
218// avoid common memory leaks caused by forgetting to Release an object
219// reference. Sample usage:
220//
221// class MyFoo : public RefCounted<MyFoo> {
222// ...
223// };
224//
225// void some_function() {
226// scoped_refptr<MyFoo> foo = new MyFoo();
227// foo->Method(param);
228// // |foo| is released when this function returns
229// }
230//
231// void some_other_function() {
232// scoped_refptr<MyFoo> foo = new MyFoo();
233// ...
234// foo = NULL; // explicitly releases |foo|
235// ...
236// if (foo)
237// foo->Method(param);
238// }
239//
240// The above examples show how scoped_refptr<T> acts like a pointer to T.
241// Given two scoped_refptr<T> classes, it is also possible to exchange
242// references between the two objects, like so:
243//
244// {
245// scoped_refptr<MyFoo> a = new MyFoo();
246// scoped_refptr<MyFoo> b;
247//
248// b.swap(a);
249// // now, |b| references the MyFoo object, and |a| references NULL.
250// }
251//
252// To make both |a| and |b| in the above example reference the same MyFoo
253// object, simply use the assignment operator:
254//
255// {
256// scoped_refptr<MyFoo> a = new MyFoo();
257// scoped_refptr<MyFoo> b;
258//
259// b = a;
260// // now, |a| and |b| each own a reference to the same MyFoo object.
261// }
262//
263template <class T>
264class scoped_refptr {
265 public:
xhwang@chromium.org87cb6e32012-06-20 03:33:38 +0900266 typedef T element_type;
267
levin@chromium.org5c528682011-03-28 10:54:15 +0900268 scoped_refptr() : ptr_(NULL) {
269 }
270
271 scoped_refptr(T* p) : ptr_(p) {
272 if (ptr_)
273 ptr_->AddRef();
274 }
275
276 scoped_refptr(const scoped_refptr<T>& r) : ptr_(r.ptr_) {
277 if (ptr_)
278 ptr_->AddRef();
279 }
280
281 template <typename U>
282 scoped_refptr(const scoped_refptr<U>& r) : ptr_(r.get()) {
283 if (ptr_)
284 ptr_->AddRef();
285 }
286
287 ~scoped_refptr() {
288 if (ptr_)
289 ptr_->Release();
290 }
291
292 T* get() const { return ptr_; }
mikhail.pozdnyakov@intel.com3d815722013-10-21 23:16:31 +0900293
294 // Allow scoped_refptr<C> to be used in boolean expression
295 // and comparison operations.
levin@chromium.org5c528682011-03-28 10:54:15 +0900296 operator T*() const { return ptr_; }
mikhail.pozdnyakov@intel.com3d815722013-10-21 23:16:31 +0900297
akalin@chromium.orgee0b43d2012-01-31 11:16:55 +0900298 T* operator->() const {
299 assert(ptr_ != NULL);
300 return ptr_;
301 }
levin@chromium.org5c528682011-03-28 10:54:15 +0900302
levin@chromium.org5c528682011-03-28 10:54:15 +0900303 scoped_refptr<T>& operator=(T* p) {
304 // AddRef first so that self assignment should work
305 if (p)
306 p->AddRef();
mnaganov@chromium.org08a60f52012-01-05 19:52:55 +0900307 T* old_ptr = ptr_;
levin@chromium.org5c528682011-03-28 10:54:15 +0900308 ptr_ = p;
mnaganov@chromium.org08a60f52012-01-05 19:52:55 +0900309 if (old_ptr)
310 old_ptr->Release();
levin@chromium.org5c528682011-03-28 10:54:15 +0900311 return *this;
312 }
313
314 scoped_refptr<T>& operator=(const scoped_refptr<T>& r) {
315 return *this = r.ptr_;
316 }
317
318 template <typename U>
319 scoped_refptr<T>& operator=(const scoped_refptr<U>& r) {
320 return *this = r.get();
321 }
322
323 void swap(T** pp) {
324 T* p = ptr_;
325 ptr_ = *pp;
326 *pp = p;
327 }
328
329 void swap(scoped_refptr<T>& r) {
330 swap(&r.ptr_);
331 }
332
333 protected:
334 T* ptr_;
335};
336
337// Handy utility for creating a scoped_refptr<T> out of a T* explicitly without
338// having to retype all the template arguments
339template <typename T>
340scoped_refptr<T> make_scoped_refptr(T* t) {
341 return scoped_refptr<T>(t);
342}
343
344#endif // BASE_MEMORY_REF_COUNTED_H_