blob: 95fa565a3ad81efb5a7f96f2ac3424e298a64aac [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"
Alex Vakulenko674f0eb2016-01-20 08:10:48 -080014#include "base/macros.h"
Vitaly Bukacbed2062015-08-17 12:54:05 -070015#include "base/logging.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//
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800108// You should always make your destructor non-public, to avoid any code deleting
Vitaly Bukacbed2062015-08-17 12:54:05 -0700109// 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 {
Vitaly Bukacbed2062015-08-17 12:54:05 -0700255 public:
256 typedef T element_type;
257
258 scoped_refptr() : ptr_(NULL) {
259 }
260
261 scoped_refptr(T* p) : ptr_(p) {
262 if (ptr_)
263 AddRef(ptr_);
264 }
265
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800266 // Copy constructor.
Vitaly Bukacbed2062015-08-17 12:54:05 -0700267 scoped_refptr(const scoped_refptr<T>& r) : ptr_(r.ptr_) {
268 if (ptr_)
269 AddRef(ptr_);
270 }
271
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800272 // Copy conversion constructor.
Vitaly Bukacbed2062015-08-17 12:54:05 -0700273 template <typename U>
274 scoped_refptr(const scoped_refptr<U>& r) : ptr_(r.get()) {
275 if (ptr_)
276 AddRef(ptr_);
277 }
278
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800279 // Move constructor. This is required in addition to the conversion
280 // constructor below in order for clang to warn about pessimizing moves.
281 scoped_refptr(scoped_refptr&& r) : ptr_(r.get()) { r.ptr_ = nullptr; }
282
283 // Move conversion constructor.
Vitaly Bukacbed2062015-08-17 12:54:05 -0700284 template <typename U>
285 scoped_refptr(scoped_refptr<U>&& r) : ptr_(r.get()) {
286 r.ptr_ = nullptr;
287 }
288
289 ~scoped_refptr() {
290 if (ptr_)
291 Release(ptr_);
292 }
293
294 T* get() const { return ptr_; }
295
296 T& operator*() const {
297 assert(ptr_ != NULL);
298 return *ptr_;
299 }
300
301 T* operator->() const {
302 assert(ptr_ != NULL);
303 return ptr_;
304 }
305
306 scoped_refptr<T>& operator=(T* p) {
307 // AddRef first so that self assignment should work
308 if (p)
309 AddRef(p);
310 T* old_ptr = ptr_;
311 ptr_ = p;
312 if (old_ptr)
313 Release(old_ptr);
314 return *this;
315 }
316
317 scoped_refptr<T>& operator=(const scoped_refptr<T>& r) {
318 return *this = r.ptr_;
319 }
320
321 template <typename U>
322 scoped_refptr<T>& operator=(const scoped_refptr<U>& r) {
323 return *this = r.get();
324 }
325
326 scoped_refptr<T>& operator=(scoped_refptr<T>&& r) {
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800327 scoped_refptr<T>(std::move(r)).swap(*this);
Vitaly Bukacbed2062015-08-17 12:54:05 -0700328 return *this;
329 }
330
331 template <typename U>
332 scoped_refptr<T>& operator=(scoped_refptr<U>&& r) {
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800333 scoped_refptr<T>(std::move(r)).swap(*this);
Vitaly Bukacbed2062015-08-17 12:54:05 -0700334 return *this;
335 }
336
337 void swap(T** pp) {
338 T* p = ptr_;
339 ptr_ = *pp;
340 *pp = p;
341 }
342
343 void swap(scoped_refptr<T>& r) {
344 swap(&r.ptr_);
345 }
346
347 private:
348 template <typename U> friend class scoped_refptr;
349
350 // Allow scoped_refptr<T> to be used in boolean expressions, but not
351 // implicitly convertible to a real bool (which is dangerous).
352 //
353 // Note that this trick is only safe when the == and != operators
354 // are declared explicitly, as otherwise "refptr1 == refptr2"
355 // will compile but do the wrong thing (i.e., convert to Testable
356 // and then do the comparison).
357 typedef T* scoped_refptr::*Testable;
358
359 public:
360 operator Testable() const { return ptr_ ? &scoped_refptr::ptr_ : nullptr; }
361
362 template <typename U>
363 bool operator==(const scoped_refptr<U>& rhs) const {
364 return ptr_ == rhs.get();
365 }
366
367 template <typename U>
368 bool operator!=(const scoped_refptr<U>& rhs) const {
369 return !operator==(rhs);
370 }
371
372 template <typename U>
373 bool operator<(const scoped_refptr<U>& rhs) const {
374 return ptr_ < rhs.get();
375 }
376
377 protected:
378 T* ptr_;
379
380 private:
381 // Non-inline helpers to allow:
382 // class Opaque;
383 // extern template class scoped_refptr<Opaque>;
384 // Otherwise the compiler will complain that Opaque is an incomplete type.
385 static void AddRef(T* ptr);
386 static void Release(T* ptr);
387};
388
389template <typename T>
390void scoped_refptr<T>::AddRef(T* ptr) {
391 ptr->AddRef();
392}
393
394template <typename T>
395void scoped_refptr<T>::Release(T* ptr) {
396 ptr->Release();
397}
398
399// Handy utility for creating a scoped_refptr<T> out of a T* explicitly without
400// having to retype all the template arguments
401template <typename T>
402scoped_refptr<T> make_scoped_refptr(T* t) {
403 return scoped_refptr<T>(t);
404}
405
406// Temporary operator overloads to facilitate the transition. See
407// https://crbug.com/110610.
408template <typename T, typename U>
409bool operator==(const scoped_refptr<T>& lhs, const U* rhs) {
410 return lhs.get() == rhs;
411}
412
413template <typename T, typename U>
414bool operator==(const T* lhs, const scoped_refptr<U>& rhs) {
415 return lhs == rhs.get();
416}
417
418template <typename T, typename U>
419bool operator!=(const scoped_refptr<T>& lhs, const U* rhs) {
420 return !operator==(lhs, rhs);
421}
422
423template <typename T, typename U>
424bool operator!=(const T* lhs, const scoped_refptr<U>& rhs) {
425 return !operator==(lhs, rhs);
426}
427
428template <typename T>
429std::ostream& operator<<(std::ostream& out, const scoped_refptr<T>& p) {
430 return out << p.get();
431}
432
433#endif // BASE_MEMORY_REF_COUNTED_H_