blob: 853fa906e38d790ed0e8d8853e8e98a65246c7bd [file] [log] [blame]
license.botbf09a502008-08-24 00:55:551// Copyright (c) 2006-2008 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.
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_
initial.commitd7cae122008-07-26 21:49:387
[email protected]f9be5382008-08-06 11:55:428#include "base/atomic_ref_count.h"
initial.commitd7cae122008-07-26 21:49:389#include "base/basictypes.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 {
17 protected:
18 RefCountedBase();
19 ~RefCountedBase();
20
21 void AddRef();
22
23 // Returns true if the object should self-delete.
24 bool Release();
25
26 private:
27 int ref_count_;
28#ifndef NDEBUG
29 bool in_dtor_;
30#endif
31
[email protected]0d02a5f2009-01-26 19:29:0732 DFAKE_MUTEX(add_release_);
33
[email protected]1eb89e82008-08-15 12:27:0334 DISALLOW_COPY_AND_ASSIGN(RefCountedBase);
35};
36
37class RefCountedThreadSafeBase {
38 protected:
39 RefCountedThreadSafeBase();
40 ~RefCountedThreadSafeBase();
41
42 void AddRef();
43
44 // Returns true if the object should self-delete.
45 bool Release();
46
47 private:
48 AtomicRefCount ref_count_;
49#ifndef NDEBUG
50 bool in_dtor_;
51#endif
52
53 DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafeBase);
54};
55
56
57
58} // namespace subtle
59
initial.commitd7cae122008-07-26 21:49:3860//
61// A base class for reference counted classes. Otherwise, known as a cheap
62// knock-off of WebKit's RefCounted<T> class. To use this guy just extend your
63// class from it like so:
64//
65// class MyFoo : public base::RefCounted<MyFoo> {
66// ...
67// };
68//
69template <class T>
[email protected]1eb89e82008-08-15 12:27:0370class RefCounted : public subtle::RefCountedBase {
initial.commitd7cae122008-07-26 21:49:3871 public:
[email protected]1eb89e82008-08-15 12:27:0372 RefCounted() { }
73 ~RefCounted() { }
initial.commitd7cae122008-07-26 21:49:3874
75 void AddRef() {
[email protected]1eb89e82008-08-15 12:27:0376 subtle::RefCountedBase::AddRef();
initial.commitd7cae122008-07-26 21:49:3877 }
78
79 void Release() {
[email protected]1eb89e82008-08-15 12:27:0380 if (subtle::RefCountedBase::Release()) {
initial.commitd7cae122008-07-26 21:49:3881 delete static_cast<T*>(this);
82 }
83 }
84
85 private:
[email protected]1eb89e82008-08-15 12:27:0386 DISALLOW_COPY_AND_ASSIGN(RefCounted<T>);
initial.commitd7cae122008-07-26 21:49:3887};
88
89//
90// A thread-safe variant of RefCounted<T>
91//
92// class MyFoo : public base::RefCountedThreadSafe<MyFoo> {
93// ...
94// };
95//
96template <class T>
[email protected]1eb89e82008-08-15 12:27:0397class RefCountedThreadSafe : public subtle::RefCountedThreadSafeBase {
initial.commitd7cae122008-07-26 21:49:3898 public:
[email protected]1eb89e82008-08-15 12:27:0399 RefCountedThreadSafe() { }
100 ~RefCountedThreadSafe() { }
initial.commitd7cae122008-07-26 21:49:38101
102 void AddRef() {
[email protected]1eb89e82008-08-15 12:27:03103 subtle::RefCountedThreadSafeBase::AddRef();
initial.commitd7cae122008-07-26 21:49:38104 }
105
106 void Release() {
[email protected]1eb89e82008-08-15 12:27:03107 if (subtle::RefCountedThreadSafeBase::Release()) {
initial.commitd7cae122008-07-26 21:49:38108 delete static_cast<T*>(this);
109 }
110 }
111
[email protected]be2cfb002008-12-10 17:42:21112 private:
[email protected]1eb89e82008-08-15 12:27:03113 DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafe<T>);
initial.commitd7cae122008-07-26 21:49:38114};
115
[email protected]0aa55312008-10-17 21:53:08116//
117// A wrapper for some piece of data so we can place other things in
118// scoped_refptrs<>.
119//
120template<typename T>
121class RefCountedData : public base::RefCounted< base::RefCountedData<T> > {
122 public:
123 RefCountedData() : data() {}
124 RefCountedData(const T& in_value) : data(in_value) {}
125
126 T data;
127};
128
[email protected]38c1fb712008-08-15 13:35:59129} // namespace base
initial.commitd7cae122008-07-26 21:49:38130
131//
132// A smart pointer class for reference counted objects. Use this class instead
133// of calling AddRef and Release manually on a reference counted object to
134// avoid common memory leaks caused by forgetting to Release an object
135// reference. Sample usage:
136//
137// class MyFoo : public RefCounted<MyFoo> {
138// ...
139// };
140//
141// void some_function() {
142// scoped_refptr<MyFoo> foo = new MyFoo();
143// foo->Method(param);
144// // |foo| is released when this function returns
145// }
146//
147// void some_other_function() {
148// scoped_refptr<MyFoo> foo = new MyFoo();
149// ...
150// foo = NULL; // explicitly releases |foo|
151// ...
152// if (foo)
153// foo->Method(param);
154// }
155//
156// The above examples show how scoped_refptr<T> acts like a pointer to T.
157// Given two scoped_refptr<T> classes, it is also possible to exchange
158// references between the two objects, like so:
159//
160// {
161// scoped_refptr<MyFoo> a = new MyFoo();
162// scoped_refptr<MyFoo> b;
163//
164// b.swap(a);
165// // now, |b| references the MyFoo object, and |a| references NULL.
166// }
167//
168// To make both |a| and |b| in the above example reference the same MyFoo
169// object, simply use the assignment operator:
170//
171// {
172// scoped_refptr<MyFoo> a = new MyFoo();
173// scoped_refptr<MyFoo> b;
174//
175// b = a;
176// // now, |a| and |b| each own a reference to the same MyFoo object.
177// }
178//
179template <class T>
180class scoped_refptr {
181 public:
182 scoped_refptr() : ptr_(NULL) {
183 }
184
185 scoped_refptr(T* p) : ptr_(p) {
186 if (ptr_)
187 ptr_->AddRef();
188 }
189
190 scoped_refptr(const scoped_refptr<T>& r) : ptr_(r.ptr_) {
191 if (ptr_)
192 ptr_->AddRef();
193 }
194
195 ~scoped_refptr() {
196 if (ptr_)
197 ptr_->Release();
198 }
199
200 T* get() const { return ptr_; }
201 operator T*() const { return ptr_; }
202 T* operator->() const { return ptr_; }
203
204 scoped_refptr<T>& operator=(T* p) {
205 // AddRef first so that self assignment should work
206 if (p)
207 p->AddRef();
208 if (ptr_ )
209 ptr_ ->Release();
210 ptr_ = p;
211 return *this;
212 }
213
214 scoped_refptr<T>& operator=(const scoped_refptr<T>& r) {
215 return *this = r.ptr_;
216 }
217
218 void swap(T** pp) {
219 T* p = ptr_;
220 ptr_ = *pp;
221 *pp = p;
222 }
223
224 void swap(scoped_refptr<T>& r) {
225 swap(&r.ptr_);
226 }
227
[email protected]935f7762009-01-10 00:53:13228 protected:
initial.commitd7cae122008-07-26 21:49:38229 T* ptr_;
230};
231
[email protected]1eb89e82008-08-15 12:27:03232#endif // BASE_REF_COUNTED_H_