Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(17)

Side by Side Diff: base/memory/ref_counted.h

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

Powered by Google App Engine
This is Rietveld 408576698