blob: 595a55164fdb976f7c23764e92268e6f41f15050 [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"
initial.commitd7cae122008-07-26 21:49:3810
11namespace base {
12
[email protected]1eb89e82008-08-15 12:27:0313namespace subtle {
14
15class RefCountedBase {
16 protected:
17 RefCountedBase();
18 ~RefCountedBase();
19
20 void AddRef();
21
22 // Returns true if the object should self-delete.
23 bool Release();
24
25 private:
26 int ref_count_;
27#ifndef NDEBUG
28 bool in_dtor_;
29#endif
30
31 DISALLOW_COPY_AND_ASSIGN(RefCountedBase);
32};
33
34class RefCountedThreadSafeBase {
35 protected:
36 RefCountedThreadSafeBase();
37 ~RefCountedThreadSafeBase();
38
39 void AddRef();
40
41 // Returns true if the object should self-delete.
42 bool Release();
43
44 private:
45 AtomicRefCount ref_count_;
46#ifndef NDEBUG
47 bool in_dtor_;
48#endif
49
50 DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafeBase);
51};
52
53
54
55} // namespace subtle
56
initial.commitd7cae122008-07-26 21:49:3857//
58// A base class for reference counted classes. Otherwise, known as a cheap
59// knock-off of WebKit's RefCounted<T> class. To use this guy just extend your
60// class from it like so:
61//
62// class MyFoo : public base::RefCounted<MyFoo> {
63// ...
64// };
65//
66template <class T>
[email protected]1eb89e82008-08-15 12:27:0367class RefCounted : public subtle::RefCountedBase {
initial.commitd7cae122008-07-26 21:49:3868 public:
[email protected]1eb89e82008-08-15 12:27:0369 RefCounted() { }
70 ~RefCounted() { }
initial.commitd7cae122008-07-26 21:49:3871
72 void AddRef() {
[email protected]1eb89e82008-08-15 12:27:0373 subtle::RefCountedBase::AddRef();
initial.commitd7cae122008-07-26 21:49:3874 }
75
76 void Release() {
[email protected]1eb89e82008-08-15 12:27:0377 if (subtle::RefCountedBase::Release()) {
initial.commitd7cae122008-07-26 21:49:3878 delete static_cast<T*>(this);
79 }
80 }
81
82 private:
[email protected]1eb89e82008-08-15 12:27:0383 DISALLOW_COPY_AND_ASSIGN(RefCounted<T>);
initial.commitd7cae122008-07-26 21:49:3884};
85
86//
87// A thread-safe variant of RefCounted<T>
88//
89// class MyFoo : public base::RefCountedThreadSafe<MyFoo> {
90// ...
91// };
92//
93template <class T>
[email protected]1eb89e82008-08-15 12:27:0394class RefCountedThreadSafe : public subtle::RefCountedThreadSafeBase {
initial.commitd7cae122008-07-26 21:49:3895 public:
[email protected]1eb89e82008-08-15 12:27:0396 RefCountedThreadSafe() { }
97 ~RefCountedThreadSafe() { }
initial.commitd7cae122008-07-26 21:49:3898
99 void AddRef() {
[email protected]1eb89e82008-08-15 12:27:03100 subtle::RefCountedThreadSafeBase::AddRef();
initial.commitd7cae122008-07-26 21:49:38101 }
102
103 void Release() {
[email protected]1eb89e82008-08-15 12:27:03104 if (subtle::RefCountedThreadSafeBase::Release()) {
initial.commitd7cae122008-07-26 21:49:38105 delete static_cast<T*>(this);
106 }
107 }
108
[email protected]1eb89e82008-08-15 12:27:03109 DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafe<T>);
initial.commitd7cae122008-07-26 21:49:38110};
111
[email protected]0aa55312008-10-17 21:53:08112//
113// A wrapper for some piece of data so we can place other things in
114// scoped_refptrs<>.
115//
116template<typename T>
117class RefCountedData : public base::RefCounted< base::RefCountedData<T> > {
118 public:
119 RefCountedData() : data() {}
120 RefCountedData(const T& in_value) : data(in_value) {}
121
122 T data;
123};
124
[email protected]38c1fb712008-08-15 13:35:59125} // namespace base
initial.commitd7cae122008-07-26 21:49:38126
127//
128// A smart pointer class for reference counted objects. Use this class instead
129// of calling AddRef and Release manually on a reference counted object to
130// avoid common memory leaks caused by forgetting to Release an object
131// reference. Sample usage:
132//
133// class MyFoo : public RefCounted<MyFoo> {
134// ...
135// };
136//
137// void some_function() {
138// scoped_refptr<MyFoo> foo = new MyFoo();
139// foo->Method(param);
140// // |foo| is released when this function returns
141// }
142//
143// void some_other_function() {
144// scoped_refptr<MyFoo> foo = new MyFoo();
145// ...
146// foo = NULL; // explicitly releases |foo|
147// ...
148// if (foo)
149// foo->Method(param);
150// }
151//
152// The above examples show how scoped_refptr<T> acts like a pointer to T.
153// Given two scoped_refptr<T> classes, it is also possible to exchange
154// references between the two objects, like so:
155//
156// {
157// scoped_refptr<MyFoo> a = new MyFoo();
158// scoped_refptr<MyFoo> b;
159//
160// b.swap(a);
161// // now, |b| references the MyFoo object, and |a| references NULL.
162// }
163//
164// To make both |a| and |b| in the above example reference the same MyFoo
165// object, simply use the assignment operator:
166//
167// {
168// scoped_refptr<MyFoo> a = new MyFoo();
169// scoped_refptr<MyFoo> b;
170//
171// b = a;
172// // now, |a| and |b| each own a reference to the same MyFoo object.
173// }
174//
175template <class T>
176class scoped_refptr {
177 public:
178 scoped_refptr() : ptr_(NULL) {
179 }
180
181 scoped_refptr(T* p) : ptr_(p) {
182 if (ptr_)
183 ptr_->AddRef();
184 }
185
186 scoped_refptr(const scoped_refptr<T>& r) : ptr_(r.ptr_) {
187 if (ptr_)
188 ptr_->AddRef();
189 }
190
191 ~scoped_refptr() {
192 if (ptr_)
193 ptr_->Release();
194 }
195
196 T* get() const { return ptr_; }
197 operator T*() const { return ptr_; }
198 T* operator->() const { return ptr_; }
199
200 scoped_refptr<T>& operator=(T* p) {
201 // AddRef first so that self assignment should work
202 if (p)
203 p->AddRef();
204 if (ptr_ )
205 ptr_ ->Release();
206 ptr_ = p;
207 return *this;
208 }
209
210 scoped_refptr<T>& operator=(const scoped_refptr<T>& r) {
211 return *this = r.ptr_;
212 }
213
214 void swap(T** pp) {
215 T* p = ptr_;
216 ptr_ = *pp;
217 *pp = p;
218 }
219
220 void swap(scoped_refptr<T>& r) {
221 swap(&r.ptr_);
222 }
223
224 private:
225 T* ptr_;
226};
227
[email protected]1eb89e82008-08-15 12:27:03228#endif // BASE_REF_COUNTED_H_