blob: 52e8f00d607d7f66c121e1a5717a60f30d2f6e80 [file] [log] [blame]
Vitaly Bukacbed2062015-08-17 12:54:05 -07001// Copyright (c) 2012 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.
4
5#ifndef BASE_MEMORY_REF_COUNTED_H_
6#define BASE_MEMORY_REF_COUNTED_H_
7
Vitaly Bukab1fcfc02015-09-14 10:24:39 -07008#include <atomic>
Vitaly Bukacbed2062015-08-17 12:54:05 -07009#include <cassert>
10#include <iosfwd>
11
Vitaly Bukacbed2062015-08-17 12:54:05 -070012#include "base/base_export.h"
13#include "base/compiler_specific.h"
Vitaly Bukacbed2062015-08-17 12:54:05 -070014#include "base/logging.h"
Vitaly Bukacbed2062015-08-17 12:54:05 -070015#include "base/move.h"
Alex Vakulenkof1fa8be2015-12-08 12:38:56 -080016#include "build/build_config.h"
Vitaly Bukacbed2062015-08-17 12:54:05 -070017
18namespace base {
19
20namespace subtle {
21
Vitaly Bukaf2f26402015-08-25 13:03:27 -070022class BASE_EXPORT RefCountedBase {
Vitaly Bukacbed2062015-08-17 12:54:05 -070023 public:
24 bool HasOneRef() const { return ref_count_ == 1; }
25
26 protected:
27 RefCountedBase()
28 : ref_count_(0)
29 #ifndef NDEBUG
30 , in_dtor_(false)
31 #endif
32 {
33 }
34
35 ~RefCountedBase() {
36 #ifndef NDEBUG
37 DCHECK(in_dtor_) << "RefCounted object deleted without calling Release()";
38 #endif
39 }
40
41
42 void AddRef() const {
Vitaly Bukacbed2062015-08-17 12:54:05 -070043 #ifndef NDEBUG
44 DCHECK(!in_dtor_);
45 #endif
46 ++ref_count_;
47 }
48
49 // Returns true if the object should self-delete.
50 bool Release() const {
Vitaly Bukacbed2062015-08-17 12:54:05 -070051 #ifndef NDEBUG
52 DCHECK(!in_dtor_);
53 #endif
54 if (--ref_count_ == 0) {
55 #ifndef NDEBUG
56 in_dtor_ = true;
57 #endif
58 return true;
59 }
60 return false;
61 }
62
63 private:
64 mutable int ref_count_;
65#ifndef NDEBUG
66 mutable bool in_dtor_;
67#endif
68
Vitaly Bukacbed2062015-08-17 12:54:05 -070069 DISALLOW_COPY_AND_ASSIGN(RefCountedBase);
70};
71
Vitaly Bukaf2f26402015-08-25 13:03:27 -070072class BASE_EXPORT RefCountedThreadSafeBase {
Vitaly Bukacbed2062015-08-17 12:54:05 -070073 public:
74 bool HasOneRef() const;
75
76 protected:
77 RefCountedThreadSafeBase();
78 ~RefCountedThreadSafeBase();
79
80 void AddRef() const;
81
82 // Returns true if the object should self-delete.
83 bool Release() const;
84
85 private:
Vitaly Bukab1fcfc02015-09-14 10:24:39 -070086 mutable std::atomic<int32_t> ref_count_;
Vitaly Bukacbed2062015-08-17 12:54:05 -070087#ifndef NDEBUG
88 mutable bool in_dtor_;
89#endif
90
91 DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafeBase);
92};
93
94} // namespace subtle
95
96//
97// A base class for reference counted classes. Otherwise, known as a cheap
98// knock-off of WebKit's RefCounted<T> class. To use this guy just extend your
99// class from it like so:
100//
101// class MyFoo : public base::RefCounted<MyFoo> {
102// ...
103// private:
104// friend class base::RefCounted<MyFoo>;
105// ~MyFoo();
106// };
107//
108// You should always make your destructor private, to avoid any code deleting
109// the object accidently while there are references to it.
110template <class T>
111class RefCounted : public subtle::RefCountedBase {
112 public:
113 RefCounted() {}
114
115 void AddRef() const {
116 subtle::RefCountedBase::AddRef();
117 }
118
119 void Release() const {
120 if (subtle::RefCountedBase::Release()) {
121 delete static_cast<const T*>(this);
122 }
123 }
124
125 protected:
126 ~RefCounted() {}
127
128 private:
129 DISALLOW_COPY_AND_ASSIGN(RefCounted<T>);
130};
131
132// Forward declaration.
133template <class T, typename Traits> class RefCountedThreadSafe;
134
135// Default traits for RefCountedThreadSafe<T>. Deletes the object when its ref
136// count reaches 0. Overload to delete it on a different thread etc.
137template<typename T>
138struct DefaultRefCountedThreadSafeTraits {
139 static void Destruct(const T* x) {
140 // Delete through RefCountedThreadSafe to make child classes only need to be
141 // friend with RefCountedThreadSafe instead of this struct, which is an
142 // implementation detail.
143 RefCountedThreadSafe<T,
144 DefaultRefCountedThreadSafeTraits>::DeleteInternal(x);
145 }
146};
147
148//
149// A thread-safe variant of RefCounted<T>
150//
151// class MyFoo : public base::RefCountedThreadSafe<MyFoo> {
152// ...
153// };
154//
155// If you're using the default trait, then you should add compile time
156// asserts that no one else is deleting your object. i.e.
157// private:
158// friend class base::RefCountedThreadSafe<MyFoo>;
159// ~MyFoo();
160template <class T, typename Traits = DefaultRefCountedThreadSafeTraits<T> >
161class RefCountedThreadSafe : public subtle::RefCountedThreadSafeBase {
162 public:
163 RefCountedThreadSafe() {}
164
165 void AddRef() const {
166 subtle::RefCountedThreadSafeBase::AddRef();
167 }
168
169 void Release() const {
170 if (subtle::RefCountedThreadSafeBase::Release()) {
171 Traits::Destruct(static_cast<const T*>(this));
172 }
173 }
174
175 protected:
176 ~RefCountedThreadSafe() {}
177
178 private:
179 friend struct DefaultRefCountedThreadSafeTraits<T>;
180 static void DeleteInternal(const T* x) { delete x; }
181
182 DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafe);
183};
184
185//
186// A thread-safe wrapper for some piece of data so we can place other
187// things in scoped_refptrs<>.
188//
189template<typename T>
190class RefCountedData
191 : public base::RefCountedThreadSafe< base::RefCountedData<T> > {
192 public:
193 RefCountedData() : data() {}
194 RefCountedData(const T& in_value) : data(in_value) {}
195
196 T data;
197
198 private:
199 friend class base::RefCountedThreadSafe<base::RefCountedData<T> >;
200 ~RefCountedData() {}
201};
202
203} // namespace base
204
205//
206// A smart pointer class for reference counted objects. Use this class instead
207// of calling AddRef and Release manually on a reference counted object to
208// avoid common memory leaks caused by forgetting to Release an object
209// reference. Sample usage:
210//
211// class MyFoo : public RefCounted<MyFoo> {
212// ...
213// };
214//
215// void some_function() {
216// scoped_refptr<MyFoo> foo = new MyFoo();
217// foo->Method(param);
218// // |foo| is released when this function returns
219// }
220//
221// void some_other_function() {
222// scoped_refptr<MyFoo> foo = new MyFoo();
223// ...
224// foo = NULL; // explicitly releases |foo|
225// ...
226// if (foo)
227// foo->Method(param);
228// }
229//
230// The above examples show how scoped_refptr<T> acts like a pointer to T.
231// Given two scoped_refptr<T> classes, it is also possible to exchange
232// references between the two objects, like so:
233//
234// {
235// scoped_refptr<MyFoo> a = new MyFoo();
236// scoped_refptr<MyFoo> b;
237//
238// b.swap(a);
239// // now, |b| references the MyFoo object, and |a| references NULL.
240// }
241//
242// To make both |a| and |b| in the above example reference the same MyFoo
243// object, simply use the assignment operator:
244//
245// {
246// scoped_refptr<MyFoo> a = new MyFoo();
247// scoped_refptr<MyFoo> b;
248//
249// b = a;
250// // now, |a| and |b| each own a reference to the same MyFoo object.
251// }
252//
253template <class T>
254class scoped_refptr {
255 TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(scoped_refptr)
256 public:
257 typedef T element_type;
258
259 scoped_refptr() : ptr_(NULL) {
260 }
261
262 scoped_refptr(T* p) : ptr_(p) {
263 if (ptr_)
264 AddRef(ptr_);
265 }
266
267 scoped_refptr(const scoped_refptr<T>& r) : ptr_(r.ptr_) {
268 if (ptr_)
269 AddRef(ptr_);
270 }
271
272 template <typename U>
273 scoped_refptr(const scoped_refptr<U>& r) : ptr_(r.get()) {
274 if (ptr_)
275 AddRef(ptr_);
276 }
277
278 template <typename U>
279 scoped_refptr(scoped_refptr<U>&& r) : ptr_(r.get()) {
280 r.ptr_ = nullptr;
281 }
282
283 ~scoped_refptr() {
284 if (ptr_)
285 Release(ptr_);
286 }
287
288 T* get() const { return ptr_; }
289
290 T& operator*() const {
291 assert(ptr_ != NULL);
292 return *ptr_;
293 }
294
295 T* operator->() const {
296 assert(ptr_ != NULL);
297 return ptr_;
298 }
299
300 scoped_refptr<T>& operator=(T* p) {
301 // AddRef first so that self assignment should work
302 if (p)
303 AddRef(p);
304 T* old_ptr = ptr_;
305 ptr_ = p;
306 if (old_ptr)
307 Release(old_ptr);
308 return *this;
309 }
310
311 scoped_refptr<T>& operator=(const scoped_refptr<T>& r) {
312 return *this = r.ptr_;
313 }
314
315 template <typename U>
316 scoped_refptr<T>& operator=(const scoped_refptr<U>& r) {
317 return *this = r.get();
318 }
319
320 scoped_refptr<T>& operator=(scoped_refptr<T>&& r) {
321 scoped_refptr<T>(r.Pass()).swap(*this);
322 return *this;
323 }
324
325 template <typename U>
326 scoped_refptr<T>& operator=(scoped_refptr<U>&& r) {
327 scoped_refptr<T>(r.Pass()).swap(*this);
328 return *this;
329 }
330
331 void swap(T** pp) {
332 T* p = ptr_;
333 ptr_ = *pp;
334 *pp = p;
335 }
336
337 void swap(scoped_refptr<T>& r) {
338 swap(&r.ptr_);
339 }
340
341 private:
342 template <typename U> friend class scoped_refptr;
343
344 // Allow scoped_refptr<T> to be used in boolean expressions, but not
345 // implicitly convertible to a real bool (which is dangerous).
346 //
347 // Note that this trick is only safe when the == and != operators
348 // are declared explicitly, as otherwise "refptr1 == refptr2"
349 // will compile but do the wrong thing (i.e., convert to Testable
350 // and then do the comparison).
351 typedef T* scoped_refptr::*Testable;
352
353 public:
354 operator Testable() const { return ptr_ ? &scoped_refptr::ptr_ : nullptr; }
355
356 template <typename U>
357 bool operator==(const scoped_refptr<U>& rhs) const {
358 return ptr_ == rhs.get();
359 }
360
361 template <typename U>
362 bool operator!=(const scoped_refptr<U>& rhs) const {
363 return !operator==(rhs);
364 }
365
366 template <typename U>
367 bool operator<(const scoped_refptr<U>& rhs) const {
368 return ptr_ < rhs.get();
369 }
370
371 protected:
372 T* ptr_;
373
374 private:
375 // Non-inline helpers to allow:
376 // class Opaque;
377 // extern template class scoped_refptr<Opaque>;
378 // Otherwise the compiler will complain that Opaque is an incomplete type.
379 static void AddRef(T* ptr);
380 static void Release(T* ptr);
381};
382
383template <typename T>
384void scoped_refptr<T>::AddRef(T* ptr) {
385 ptr->AddRef();
386}
387
388template <typename T>
389void scoped_refptr<T>::Release(T* ptr) {
390 ptr->Release();
391}
392
393// Handy utility for creating a scoped_refptr<T> out of a T* explicitly without
394// having to retype all the template arguments
395template <typename T>
396scoped_refptr<T> make_scoped_refptr(T* t) {
397 return scoped_refptr<T>(t);
398}
399
400// Temporary operator overloads to facilitate the transition. See
401// https://crbug.com/110610.
402template <typename T, typename U>
403bool operator==(const scoped_refptr<T>& lhs, const U* rhs) {
404 return lhs.get() == rhs;
405}
406
407template <typename T, typename U>
408bool operator==(const T* lhs, const scoped_refptr<U>& rhs) {
409 return lhs == rhs.get();
410}
411
412template <typename T, typename U>
413bool operator!=(const scoped_refptr<T>& lhs, const U* rhs) {
414 return !operator==(lhs, rhs);
415}
416
417template <typename T, typename U>
418bool operator!=(const T* lhs, const scoped_refptr<U>& rhs) {
419 return !operator==(lhs, rhs);
420}
421
422template <typename T>
423std::ostream& operator<<(std::ostream& out, const scoped_refptr<T>& p) {
424 return out << p.get();
425}
426
427#endif // BASE_MEMORY_REF_COUNTED_H_