blob: 0e0ea67d393a6a36a2240e71cee2e276e6cd1d4b [file] [log] [blame]
license.botf003cfe2008-08-24 09:55:55 +09001// 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.commit3f4a7322008-07-27 06:49:38 +09004
maruel@google.com65792b72008-08-15 21:27:03 +09005#ifndef BASE_REF_COUNTED_H_
6#define BASE_REF_COUNTED_H_
initial.commit3f4a7322008-07-27 06:49:38 +09007
deanm@google.comb8855f52008-08-06 20:55:42 +09008#include "base/atomic_ref_count.h"
initial.commit3f4a7322008-07-27 06:49:38 +09009#include "base/basictypes.h"
initial.commit3f4a7322008-07-27 06:49:38 +090010
11namespace base {
12
maruel@google.com65792b72008-08-15 21:27:03 +090013namespace 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.commit3f4a7322008-07-27 06:49:38 +090057//
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>
maruel@google.com65792b72008-08-15 21:27:03 +090067class RefCounted : public subtle::RefCountedBase {
initial.commit3f4a7322008-07-27 06:49:38 +090068 public:
maruel@google.com65792b72008-08-15 21:27:03 +090069 RefCounted() { }
70 ~RefCounted() { }
initial.commit3f4a7322008-07-27 06:49:38 +090071
72 void AddRef() {
maruel@google.com65792b72008-08-15 21:27:03 +090073 subtle::RefCountedBase::AddRef();
initial.commit3f4a7322008-07-27 06:49:38 +090074 }
75
76 void Release() {
maruel@google.com65792b72008-08-15 21:27:03 +090077 if (subtle::RefCountedBase::Release()) {
initial.commit3f4a7322008-07-27 06:49:38 +090078 delete static_cast<T*>(this);
79 }
80 }
81
82 private:
maruel@google.com65792b72008-08-15 21:27:03 +090083 DISALLOW_COPY_AND_ASSIGN(RefCounted<T>);
initial.commit3f4a7322008-07-27 06:49:38 +090084};
85
86//
87// A thread-safe variant of RefCounted<T>
88//
89// class MyFoo : public base::RefCountedThreadSafe<MyFoo> {
90// ...
91// };
92//
93template <class T>
maruel@google.com65792b72008-08-15 21:27:03 +090094class RefCountedThreadSafe : public subtle::RefCountedThreadSafeBase {
initial.commit3f4a7322008-07-27 06:49:38 +090095 public:
maruel@google.com65792b72008-08-15 21:27:03 +090096 RefCountedThreadSafe() { }
97 ~RefCountedThreadSafe() { }
initial.commit3f4a7322008-07-27 06:49:38 +090098
99 void AddRef() {
maruel@google.com65792b72008-08-15 21:27:03 +0900100 subtle::RefCountedThreadSafeBase::AddRef();
initial.commit3f4a7322008-07-27 06:49:38 +0900101 }
102
103 void Release() {
maruel@google.com65792b72008-08-15 21:27:03 +0900104 if (subtle::RefCountedThreadSafeBase::Release()) {
initial.commit3f4a7322008-07-27 06:49:38 +0900105 delete static_cast<T*>(this);
106 }
107 }
108
maruel@google.com65792b72008-08-15 21:27:03 +0900109 DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafe<T>);
initial.commit3f4a7322008-07-27 06:49:38 +0900110};
111
mmentovai@google.comd0841462008-08-15 22:35:59 +0900112} // namespace base
initial.commit3f4a7322008-07-27 06:49:38 +0900113
114//
115// A smart pointer class for reference counted objects. Use this class instead
116// of calling AddRef and Release manually on a reference counted object to
117// avoid common memory leaks caused by forgetting to Release an object
118// reference. Sample usage:
119//
120// class MyFoo : public RefCounted<MyFoo> {
121// ...
122// };
123//
124// void some_function() {
125// scoped_refptr<MyFoo> foo = new MyFoo();
126// foo->Method(param);
127// // |foo| is released when this function returns
128// }
129//
130// void some_other_function() {
131// scoped_refptr<MyFoo> foo = new MyFoo();
132// ...
133// foo = NULL; // explicitly releases |foo|
134// ...
135// if (foo)
136// foo->Method(param);
137// }
138//
139// The above examples show how scoped_refptr<T> acts like a pointer to T.
140// Given two scoped_refptr<T> classes, it is also possible to exchange
141// references between the two objects, like so:
142//
143// {
144// scoped_refptr<MyFoo> a = new MyFoo();
145// scoped_refptr<MyFoo> b;
146//
147// b.swap(a);
148// // now, |b| references the MyFoo object, and |a| references NULL.
149// }
150//
151// To make both |a| and |b| in the above example reference the same MyFoo
152// object, simply use the assignment operator:
153//
154// {
155// scoped_refptr<MyFoo> a = new MyFoo();
156// scoped_refptr<MyFoo> b;
157//
158// b = a;
159// // now, |a| and |b| each own a reference to the same MyFoo object.
160// }
161//
162template <class T>
163class scoped_refptr {
164 public:
165 scoped_refptr() : ptr_(NULL) {
166 }
167
168 scoped_refptr(T* p) : ptr_(p) {
169 if (ptr_)
170 ptr_->AddRef();
171 }
172
173 scoped_refptr(const scoped_refptr<T>& r) : ptr_(r.ptr_) {
174 if (ptr_)
175 ptr_->AddRef();
176 }
177
178 ~scoped_refptr() {
179 if (ptr_)
180 ptr_->Release();
181 }
182
183 T* get() const { return ptr_; }
184 operator T*() const { return ptr_; }
185 T* operator->() const { return ptr_; }
186
187 scoped_refptr<T>& operator=(T* p) {
188 // AddRef first so that self assignment should work
189 if (p)
190 p->AddRef();
191 if (ptr_ )
192 ptr_ ->Release();
193 ptr_ = p;
194 return *this;
195 }
196
197 scoped_refptr<T>& operator=(const scoped_refptr<T>& r) {
198 return *this = r.ptr_;
199 }
200
201 void swap(T** pp) {
202 T* p = ptr_;
203 ptr_ = *pp;
204 *pp = p;
205 }
206
207 void swap(scoped_refptr<T>& r) {
208 swap(&r.ptr_);
209 }
210
211 private:
212 T* ptr_;
213};
214
maruel@google.com65792b72008-08-15 21:27:03 +0900215#endif // BASE_REF_COUNTED_H_
license.botf003cfe2008-08-24 09:55:55 +0900216