blob: 2cc4029101f0a2d562be79f23221ff7c7b505ba1 [file] [log] [blame]
[email protected]15f80122010-07-28 16:48:101// Copyright (c) 2010 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commitd7cae122008-07-26 21:49:384
[email protected]1eb89e82008-08-15 12:27:035#ifndef BASE_REF_COUNTED_H_
6#define BASE_REF_COUNTED_H_
[email protected]32b76ef2010-07-26 23:08:247#pragma once
initial.commitd7cae122008-07-26 21:49:388
[email protected]f9be5382008-08-06 11:55:429#include "base/atomic_ref_count.h"
[email protected]0d02a5f2009-01-26 19:29:0710#include "base/thread_collision_warner.h"
initial.commitd7cae122008-07-26 21:49:3811
12namespace base {
13
[email protected]1eb89e82008-08-15 12:27:0314namespace subtle {
15
16class RefCountedBase {
[email protected]59326aac2009-09-25 23:34:3417 public:
[email protected]39fe32a2009-09-30 04:29:2018 static bool ImplementsThreadSafeReferenceCounting() { return false; }
19
[email protected]59326aac2009-09-25 23:34:3420 bool HasOneRef() const { return ref_count_ == 1; }
21
[email protected]1eb89e82008-08-15 12:27:0322 protected:
23 RefCountedBase();
24 ~RefCountedBase();
25
[email protected]41ba5512010-10-02 00:15:0226 void AddRef() const;
[email protected]1eb89e82008-08-15 12:27:0327
28 // Returns true if the object should self-delete.
[email protected]41ba5512010-10-02 00:15:0229 bool Release() const;
[email protected]1eb89e82008-08-15 12:27:0330
31 private:
[email protected]41ba5512010-10-02 00:15:0232 mutable int ref_count_;
[email protected]1eb89e82008-08-15 12:27:0333#ifndef NDEBUG
[email protected]41ba5512010-10-02 00:15:0234 mutable bool in_dtor_;
[email protected]1eb89e82008-08-15 12:27:0335#endif
36
[email protected]0d02a5f2009-01-26 19:29:0737 DFAKE_MUTEX(add_release_);
38
[email protected]1eb89e82008-08-15 12:27:0339 DISALLOW_COPY_AND_ASSIGN(RefCountedBase);
40};
41
42class RefCountedThreadSafeBase {
[email protected]59326aac2009-09-25 23:34:3443 public:
[email protected]39fe32a2009-09-30 04:29:2044 static bool ImplementsThreadSafeReferenceCounting() { return true; }
45
[email protected]59326aac2009-09-25 23:34:3446 bool HasOneRef() const;
47
[email protected]1eb89e82008-08-15 12:27:0348 protected:
49 RefCountedThreadSafeBase();
50 ~RefCountedThreadSafeBase();
51
[email protected]41ba5512010-10-02 00:15:0252 void AddRef() const;
[email protected]1eb89e82008-08-15 12:27:0353
54 // Returns true if the object should self-delete.
[email protected]41ba5512010-10-02 00:15:0255 bool Release() const;
[email protected]1eb89e82008-08-15 12:27:0356
57 private:
[email protected]41ba5512010-10-02 00:15:0258 mutable AtomicRefCount ref_count_;
[email protected]1eb89e82008-08-15 12:27:0359#ifndef NDEBUG
[email protected]41ba5512010-10-02 00:15:0260 mutable bool in_dtor_;
[email protected]1eb89e82008-08-15 12:27:0361#endif
62
63 DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafeBase);
64};
65
[email protected]1eb89e82008-08-15 12:27:0366} // namespace subtle
67
initial.commitd7cae122008-07-26 21:49:3868//
69// A base class for reference counted classes. Otherwise, known as a cheap
70// knock-off of WebKit's RefCounted<T> class. To use this guy just extend your
71// class from it like so:
72//
73// class MyFoo : public base::RefCounted<MyFoo> {
74// ...
[email protected]877d55d2009-11-05 21:53:0875// private:
76// friend class base::RefCounted<MyFoo>;
77// ~MyFoo();
initial.commitd7cae122008-07-26 21:49:3878// };
79//
[email protected]877d55d2009-11-05 21:53:0880// You should always make your destructor private, to avoid any code deleting
81// the object accidently while there are references to it.
initial.commitd7cae122008-07-26 21:49:3882template <class T>
[email protected]1eb89e82008-08-15 12:27:0383class RefCounted : public subtle::RefCountedBase {
initial.commitd7cae122008-07-26 21:49:3884 public:
[email protected]1eb89e82008-08-15 12:27:0385 RefCounted() { }
86 ~RefCounted() { }
initial.commitd7cae122008-07-26 21:49:3887
[email protected]41ba5512010-10-02 00:15:0288 void AddRef() const {
[email protected]1eb89e82008-08-15 12:27:0389 subtle::RefCountedBase::AddRef();
initial.commitd7cae122008-07-26 21:49:3890 }
91
[email protected]41ba5512010-10-02 00:15:0292 void Release() const {
[email protected]1eb89e82008-08-15 12:27:0393 if (subtle::RefCountedBase::Release()) {
[email protected]41ba5512010-10-02 00:15:0294 delete static_cast<const T*>(this);
initial.commitd7cae122008-07-26 21:49:3895 }
96 }
97
98 private:
[email protected]1eb89e82008-08-15 12:27:0399 DISALLOW_COPY_AND_ASSIGN(RefCounted<T>);
initial.commitd7cae122008-07-26 21:49:38100};
101
[email protected]f6710622009-11-02 06:10:30102// Forward declaration.
103template <class T, typename Traits> class RefCountedThreadSafe;
104
105// Default traits for RefCountedThreadSafe<T>. Deletes the object when its ref
106// count reaches 0. Overload to delete it on a different thread etc.
107template<typename T>
108struct DefaultRefCountedThreadSafeTraits {
109 static void Destruct(T* x) {
110 // Delete through RefCountedThreadSafe to make child classes only need to be
111 // friend with RefCountedThreadSafe instead of this struct, which is an
112 // implementation detail.
[email protected]15f80122010-07-28 16:48:10113 RefCountedThreadSafe<T,
114 DefaultRefCountedThreadSafeTraits>::DeleteInternal(x);
[email protected]f6710622009-11-02 06:10:30115 }
116};
117
initial.commitd7cae122008-07-26 21:49:38118//
119// A thread-safe variant of RefCounted<T>
120//
121// class MyFoo : public base::RefCountedThreadSafe<MyFoo> {
122// ...
123// };
124//
[email protected]877d55d2009-11-05 21:53:08125// If you're using the default trait, then you should add compile time
[email protected]f6710622009-11-02 06:10:30126// asserts that no one else is deleting your object. i.e.
127// private:
[email protected]877d55d2009-11-05 21:53:08128// friend class base::RefCountedThreadSafe<MyFoo>;
[email protected]f6710622009-11-02 06:10:30129// ~MyFoo();
130template <class T, typename Traits = DefaultRefCountedThreadSafeTraits<T> >
[email protected]1eb89e82008-08-15 12:27:03131class RefCountedThreadSafe : public subtle::RefCountedThreadSafeBase {
initial.commitd7cae122008-07-26 21:49:38132 public:
[email protected]1eb89e82008-08-15 12:27:03133 RefCountedThreadSafe() { }
134 ~RefCountedThreadSafe() { }
initial.commitd7cae122008-07-26 21:49:38135
136 void AddRef() {
[email protected]1eb89e82008-08-15 12:27:03137 subtle::RefCountedThreadSafeBase::AddRef();
initial.commitd7cae122008-07-26 21:49:38138 }
139
140 void Release() {
[email protected]1eb89e82008-08-15 12:27:03141 if (subtle::RefCountedThreadSafeBase::Release()) {
[email protected]f6710622009-11-02 06:10:30142 Traits::Destruct(static_cast<T*>(this));
initial.commitd7cae122008-07-26 21:49:38143 }
144 }
145
[email protected]be2cfb002008-12-10 17:42:21146 private:
[email protected]f6710622009-11-02 06:10:30147 friend struct DefaultRefCountedThreadSafeTraits<T>;
148 static void DeleteInternal(T* x) { delete x; }
149
150 DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafe);
initial.commitd7cae122008-07-26 21:49:38151};
152
[email protected]0aa55312008-10-17 21:53:08153//
154// A wrapper for some piece of data so we can place other things in
155// scoped_refptrs<>.
156//
157template<typename T>
158class RefCountedData : public base::RefCounted< base::RefCountedData<T> > {
159 public:
160 RefCountedData() : data() {}
161 RefCountedData(const T& in_value) : data(in_value) {}
162
163 T data;
164};
165
[email protected]38c1fb712008-08-15 13:35:59166} // namespace base
initial.commitd7cae122008-07-26 21:49:38167
168//
169// A smart pointer class for reference counted objects. Use this class instead
170// of calling AddRef and Release manually on a reference counted object to
171// avoid common memory leaks caused by forgetting to Release an object
172// reference. Sample usage:
173//
174// class MyFoo : public RefCounted<MyFoo> {
175// ...
176// };
177//
178// void some_function() {
179// scoped_refptr<MyFoo> foo = new MyFoo();
180// foo->Method(param);
181// // |foo| is released when this function returns
182// }
183//
184// void some_other_function() {
185// scoped_refptr<MyFoo> foo = new MyFoo();
186// ...
187// foo = NULL; // explicitly releases |foo|
188// ...
189// if (foo)
190// foo->Method(param);
191// }
192//
193// The above examples show how scoped_refptr<T> acts like a pointer to T.
194// Given two scoped_refptr<T> classes, it is also possible to exchange
195// references between the two objects, like so:
196//
197// {
198// scoped_refptr<MyFoo> a = new MyFoo();
199// scoped_refptr<MyFoo> b;
200//
201// b.swap(a);
202// // now, |b| references the MyFoo object, and |a| references NULL.
203// }
204//
205// To make both |a| and |b| in the above example reference the same MyFoo
206// object, simply use the assignment operator:
207//
208// {
209// scoped_refptr<MyFoo> a = new MyFoo();
210// scoped_refptr<MyFoo> b;
211//
212// b = a;
213// // now, |a| and |b| each own a reference to the same MyFoo object.
214// }
215//
216template <class T>
217class scoped_refptr {
218 public:
219 scoped_refptr() : ptr_(NULL) {
220 }
221
222 scoped_refptr(T* p) : ptr_(p) {
223 if (ptr_)
224 ptr_->AddRef();
225 }
226
227 scoped_refptr(const scoped_refptr<T>& r) : ptr_(r.ptr_) {
228 if (ptr_)
229 ptr_->AddRef();
230 }
231
[email protected]f8f82502009-11-20 23:14:23232 template <typename U>
233 scoped_refptr(const scoped_refptr<U>& r) : ptr_(r.get()) {
234 if (ptr_)
235 ptr_->AddRef();
236 }
237
initial.commitd7cae122008-07-26 21:49:38238 ~scoped_refptr() {
239 if (ptr_)
240 ptr_->Release();
241 }
242
243 T* get() const { return ptr_; }
244 operator T*() const { return ptr_; }
245 T* operator->() const { return ptr_; }
246
[email protected]a5da6d612009-08-04 02:00:56247 // Release a pointer.
248 // The return value is the current pointer held by this object.
249 // If this object holds a NULL pointer, the return value is NULL.
250 // After this operation, this object will hold a NULL pointer,
251 // and will not own the object any more.
252 T* release() {
253 T* retVal = ptr_;
254 ptr_ = NULL;
255 return retVal;
256 }
257
initial.commitd7cae122008-07-26 21:49:38258 scoped_refptr<T>& operator=(T* p) {
259 // AddRef first so that self assignment should work
260 if (p)
261 p->AddRef();
262 if (ptr_ )
263 ptr_ ->Release();
264 ptr_ = p;
265 return *this;
266 }
267
268 scoped_refptr<T>& operator=(const scoped_refptr<T>& r) {
269 return *this = r.ptr_;
270 }
271
[email protected]f8f82502009-11-20 23:14:23272 template <typename U>
273 scoped_refptr<T>& operator=(const scoped_refptr<U>& r) {
274 return *this = r.get();
275 }
276
initial.commitd7cae122008-07-26 21:49:38277 void swap(T** pp) {
278 T* p = ptr_;
279 ptr_ = *pp;
280 *pp = p;
281 }
282
283 void swap(scoped_refptr<T>& r) {
284 swap(&r.ptr_);
285 }
286
[email protected]935f7762009-01-10 00:53:13287 protected:
initial.commitd7cae122008-07-26 21:49:38288 T* ptr_;
289};
290
[email protected]f8f82502009-11-20 23:14:23291// Handy utility for creating a scoped_refptr<T> out of a T* explicitly without
292// having to retype all the template arguments
293template <typename T>
294scoped_refptr<T> make_scoped_refptr(T* t) {
295 return scoped_refptr<T>(t);
296}
297
[email protected]1eb89e82008-08-15 12:27:03298#endif // BASE_REF_COUNTED_H_