OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef BASE_MEMORY_REF_COUNTED_H_ | 5 #ifndef BASE_MEMORY_REF_COUNTED_H_ |
6 #define BASE_MEMORY_REF_COUNTED_H_ | 6 #define BASE_MEMORY_REF_COUNTED_H_ |
7 | 7 |
8 #include <stddef.h> | 8 #include <stddef.h> |
9 | 9 |
10 #include <cassert> | 10 #include <cassert> |
11 #include <iosfwd> | 11 #include <iosfwd> |
12 #include <type_traits> | 12 #include <type_traits> |
13 | 13 |
14 #include "base/atomic_ref_count.h" | 14 #include "base/atomic_ref_count.h" |
15 #include "base/base_export.h" | 15 #include "base/base_export.h" |
16 #include "base/compiler_specific.h" | 16 #include "base/compiler_specific.h" |
17 #include "base/logging.h" | |
17 #include "base/macros.h" | 18 #include "base/macros.h" |
18 #ifndef NDEBUG | |
19 #include "base/logging.h" | |
20 #endif | |
21 #include "base/threading/thread_collision_warner.h" | 19 #include "base/threading/thread_collision_warner.h" |
22 #include "build/build_config.h" | 20 #include "build/build_config.h" |
23 | 21 |
24 namespace base { | 22 namespace base { |
25 | 23 |
26 namespace subtle { | 24 namespace subtle { |
27 | 25 |
28 class BASE_EXPORT RefCountedBase { | 26 class BASE_EXPORT RefCountedBase { |
29 public: | 27 public: |
30 bool HasOneRef() const { return ref_count_ == 1; } | 28 bool HasOneRef() const { return ref_count_ == 1; } |
31 | 29 |
32 protected: | 30 protected: |
33 RefCountedBase() | 31 RefCountedBase() |
34 : ref_count_(0) | 32 : ref_count_(0) |
35 #ifndef NDEBUG | 33 #if DCHECK_IS_ON() |
36 , in_dtor_(false) | 34 , in_dtor_(false) |
37 #endif | 35 #endif |
38 { | 36 { |
39 } | 37 } |
40 | 38 |
41 ~RefCountedBase() { | 39 ~RefCountedBase() { |
42 #ifndef NDEBUG | 40 #if DCHECK_IS_ON() |
43 DCHECK(in_dtor_) << "RefCounted object deleted without calling Release()"; | 41 DCHECK(in_dtor_) << "RefCounted object deleted without calling Release()"; |
44 #endif | 42 #endif |
45 } | 43 } |
46 | 44 |
47 | 45 |
48 void AddRef() const { | 46 void AddRef() const { |
49 // TODO(maruel): Add back once it doesn't assert 500 times/sec. | 47 // TODO(maruel): Add back once it doesn't assert 500 times/sec. |
50 // Current thread books the critical section "AddRelease" | 48 // Current thread books the critical section "AddRelease" |
51 // without release it. | 49 // without release it. |
52 // DFAKE_SCOPED_LOCK_THREAD_LOCKED(add_release_); | 50 // DFAKE_SCOPED_LOCK_THREAD_LOCKED(add_release_); |
53 #ifndef NDEBUG | 51 #if DCHECK_IS_ON() |
54 DCHECK(!in_dtor_); | 52 DCHECK(!in_dtor_); |
55 #endif | 53 #endif |
56 ++ref_count_; | 54 ++ref_count_; |
57 } | 55 } |
58 | 56 |
59 // Returns true if the object should self-delete. | 57 // Returns true if the object should self-delete. |
60 bool Release() const { | 58 bool Release() const { |
61 // TODO(maruel): Add back once it doesn't assert 500 times/sec. | 59 // TODO(maruel): Add back once it doesn't assert 500 times/sec. |
62 // Current thread books the critical section "AddRelease" | 60 // Current thread books the critical section "AddRelease" |
63 // without release it. | 61 // without release it. |
64 // DFAKE_SCOPED_LOCK_THREAD_LOCKED(add_release_); | 62 // DFAKE_SCOPED_LOCK_THREAD_LOCKED(add_release_); |
65 #ifndef NDEBUG | 63 #if DCHECK_IS_ON() |
66 DCHECK(!in_dtor_); | 64 DCHECK(!in_dtor_); |
67 #endif | 65 #endif |
68 if (--ref_count_ == 0) { | 66 if (--ref_count_ == 0) { |
69 #ifndef NDEBUG | 67 #if DCHECK_IS_ON() |
70 in_dtor_ = true; | 68 in_dtor_ = true; |
71 #endif | 69 #endif |
72 return true; | 70 return true; |
73 } | 71 } |
74 return false; | 72 return false; |
75 } | 73 } |
76 | 74 |
77 private: | 75 private: |
78 mutable size_t ref_count_; | 76 mutable size_t ref_count_; |
79 #ifndef NDEBUG | 77 #if DCHECK_IS_ON() |
80 mutable bool in_dtor_; | 78 mutable bool in_dtor_; |
81 #endif | 79 #endif |
82 | 80 |
83 DFAKE_MUTEX(add_release_); | 81 DFAKE_MUTEX(add_release_); |
84 | 82 |
85 DISALLOW_COPY_AND_ASSIGN(RefCountedBase); | 83 DISALLOW_COPY_AND_ASSIGN(RefCountedBase); |
86 }; | 84 }; |
87 | 85 |
88 class BASE_EXPORT RefCountedThreadSafeBase { | 86 class BASE_EXPORT RefCountedThreadSafeBase { |
89 public: | 87 public: |
90 bool HasOneRef() const; | 88 bool HasOneRef() const; |
91 | 89 |
92 protected: | 90 protected: |
93 RefCountedThreadSafeBase(); | 91 RefCountedThreadSafeBase(); |
94 ~RefCountedThreadSafeBase(); | 92 ~RefCountedThreadSafeBase(); |
95 | 93 |
96 void AddRef() const; | 94 void AddRef() const; |
97 | 95 |
98 // Returns true if the object should self-delete. | 96 // Returns true if the object should self-delete. |
99 bool Release() const; | 97 bool Release() const; |
100 | 98 |
101 private: | 99 private: |
102 mutable AtomicRefCount ref_count_; | 100 mutable AtomicRefCount ref_count_; |
103 #ifndef NDEBUG | 101 #if DCHECK_IS_ON() |
104 mutable bool in_dtor_; | 102 mutable bool in_dtor_; |
105 #endif | 103 #endif |
106 | 104 |
107 DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafeBase); | 105 DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafeBase); |
108 }; | 106 }; |
109 | 107 |
110 } // namespace subtle | 108 } // namespace subtle |
111 | 109 |
112 // | 110 // |
113 // A base class for reference counted classes. Otherwise, known as a cheap | 111 // A base class for reference counted classes. Otherwise, known as a cheap |
114 // knock-off of WebKit's RefCounted<T> class. To use this, just extend your | 112 // knock-off of WebKit's RefCounted<T> class. To use this, just extend your |
115 // class from it like so: | 113 // class from it like so: |
116 // | 114 // |
117 // class MyFoo : public base::RefCounted<MyFoo> { | 115 // class MyFoo : public base::RefCounted<MyFoo> { |
118 // ... | 116 // ... |
119 // private: | 117 // private: |
120 // friend class base::RefCounted<MyFoo>; | 118 // friend class base::RefCounted<MyFoo>; |
121 // ~MyFoo(); | 119 // ~MyFoo(); |
122 // }; | 120 // }; |
123 // | 121 // |
124 // You should always make your destructor non-public, to avoid any code deleting | 122 // You should always make your destructor non-public, to avoid any code deleting |
125 // the object accidently while there are references to it. | 123 // the object accidently while there are references to it. |
126 template <class T> | 124 template <class T> |
127 class RefCounted : public subtle::RefCountedBase { | 125 class RefCounted : public subtle::RefCountedBase { |
128 public: | 126 public: |
129 RefCounted() {} | 127 RefCounted() = default; |
130 | 128 |
131 void AddRef() const { | 129 void AddRef() const { |
132 subtle::RefCountedBase::AddRef(); | 130 subtle::RefCountedBase::AddRef(); |
133 } | 131 } |
134 | 132 |
135 void Release() const { | 133 void Release() const { |
136 if (subtle::RefCountedBase::Release()) { | 134 if (subtle::RefCountedBase::Release()) { |
137 delete static_cast<const T*>(this); | 135 delete static_cast<const T*>(this); |
138 } | 136 } |
139 } | 137 } |
140 | 138 |
141 protected: | 139 protected: |
142 ~RefCounted() {} | 140 ~RefCounted() = default; |
143 | 141 |
144 private: | 142 private: |
145 DISALLOW_COPY_AND_ASSIGN(RefCounted<T>); | 143 DISALLOW_COPY_AND_ASSIGN(RefCounted<T>); |
146 }; | 144 }; |
147 | 145 |
148 // Forward declaration. | 146 // Forward declaration. |
149 template <class T, typename Traits> class RefCountedThreadSafe; | 147 template <class T, typename Traits> class RefCountedThreadSafe; |
150 | 148 |
151 // Default traits for RefCountedThreadSafe<T>. Deletes the object when its ref | 149 // Default traits for RefCountedThreadSafe<T>. Deletes the object when its ref |
152 // count reaches 0. Overload to delete it on a different thread etc. | 150 // count reaches 0. Overload to delete it on a different thread etc. |
(...skipping 16 matching lines...) Expand all Loading... | |
169 // }; | 167 // }; |
170 // | 168 // |
171 // If you're using the default trait, then you should add compile time | 169 // If you're using the default trait, then you should add compile time |
172 // asserts that no one else is deleting your object. i.e. | 170 // asserts that no one else is deleting your object. i.e. |
173 // private: | 171 // private: |
174 // friend class base::RefCountedThreadSafe<MyFoo>; | 172 // friend class base::RefCountedThreadSafe<MyFoo>; |
175 // ~MyFoo(); | 173 // ~MyFoo(); |
176 template <class T, typename Traits = DefaultRefCountedThreadSafeTraits<T> > | 174 template <class T, typename Traits = DefaultRefCountedThreadSafeTraits<T> > |
177 class RefCountedThreadSafe : public subtle::RefCountedThreadSafeBase { | 175 class RefCountedThreadSafe : public subtle::RefCountedThreadSafeBase { |
178 public: | 176 public: |
179 RefCountedThreadSafe() {} | 177 RefCountedThreadSafe() = default; |
180 | 178 |
181 void AddRef() const { | 179 void AddRef() const { |
182 subtle::RefCountedThreadSafeBase::AddRef(); | 180 subtle::RefCountedThreadSafeBase::AddRef(); |
183 } | 181 } |
184 | 182 |
185 void Release() const { | 183 void Release() const { |
186 if (subtle::RefCountedThreadSafeBase::Release()) { | 184 if (subtle::RefCountedThreadSafeBase::Release()) { |
187 Traits::Destruct(static_cast<const T*>(this)); | 185 Traits::Destruct(static_cast<const T*>(this)); |
188 } | 186 } |
189 } | 187 } |
190 | 188 |
191 protected: | 189 protected: |
192 ~RefCountedThreadSafe() {} | 190 ~RefCountedThreadSafe() = default; |
193 | 191 |
194 private: | 192 private: |
195 friend struct DefaultRefCountedThreadSafeTraits<T>; | 193 friend struct DefaultRefCountedThreadSafeTraits<T>; |
196 static void DeleteInternal(const T* x) { delete x; } | 194 static void DeleteInternal(const T* x) { delete x; } |
197 | 195 |
198 DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafe); | 196 DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafe); |
199 }; | 197 }; |
200 | 198 |
201 // | 199 // |
202 // A thread-safe wrapper for some piece of data so we can place other | 200 // A thread-safe wrapper for some piece of data so we can place other |
203 // things in scoped_refptrs<>. | 201 // things in scoped_refptrs<>. |
204 // | 202 // |
205 template<typename T> | 203 template<typename T> |
206 class RefCountedData | 204 class RefCountedData |
207 : public base::RefCountedThreadSafe< base::RefCountedData<T> > { | 205 : public base::RefCountedThreadSafe< base::RefCountedData<T> > { |
208 public: | 206 public: |
209 RefCountedData() : data() {} | 207 RefCountedData() : data() {} |
210 RefCountedData(const T& in_value) : data(in_value) {} | 208 RefCountedData(const T& in_value) : data(in_value) {} |
211 | 209 |
212 T data; | 210 T data; |
213 | 211 |
214 private: | 212 private: |
215 friend class base::RefCountedThreadSafe<base::RefCountedData<T> >; | 213 friend class base::RefCountedThreadSafe<base::RefCountedData<T> >; |
216 ~RefCountedData() {} | 214 ~RefCountedData() = default; |
217 }; | 215 }; |
218 | 216 |
219 } // namespace base | 217 } // namespace base |
220 | 218 |
221 // | 219 // |
222 // A smart pointer class for reference counted objects. Use this class instead | 220 // A smart pointer class for reference counted objects. Use this class instead |
223 // of calling AddRef and Release manually on a reference counted object to | 221 // of calling AddRef and Release manually on a reference counted object to |
224 // avoid common memory leaks caused by forgetting to Release an object | 222 // avoid common memory leaks caused by forgetting to Release an object |
225 // reference. Sample usage: | 223 // reference. Sample usage: |
226 // | 224 // |
227 // class MyFoo : public RefCounted<MyFoo> { | 225 // class MyFoo : public RefCounted<MyFoo> { |
228 // ... | 226 // ... |
229 // }; | 227 // }; |
230 // | 228 // |
231 // void some_function() { | 229 // void some_function() { |
232 // scoped_refptr<MyFoo> foo = new MyFoo(); | 230 // scoped_refptr<MyFoo> foo = new MyFoo(); |
233 // foo->Method(param); | 231 // foo->Method(param); |
234 // // |foo| is released when this function returns | 232 // // |foo| is released when this function returns |
235 // } | 233 // } |
236 // | 234 // |
237 // void some_other_function() { | 235 // void some_other_function() { |
238 // scoped_refptr<MyFoo> foo = new MyFoo(); | 236 // scoped_refptr<MyFoo> foo = new MyFoo(); |
239 // ... | 237 // ... |
240 // foo = NULL; // explicitly releases |foo| | 238 // foo = nullptr; // explicitly releases |foo| |
241 // ... | 239 // ... |
242 // if (foo) | 240 // if (foo) |
243 // foo->Method(param); | 241 // foo->Method(param); |
244 // } | 242 // } |
245 // | 243 // |
246 // The above examples show how scoped_refptr<T> acts like a pointer to T. | 244 // The above examples show how scoped_refptr<T> acts like a pointer to T. |
247 // Given two scoped_refptr<T> classes, it is also possible to exchange | 245 // Given two scoped_refptr<T> classes, it is also possible to exchange |
248 // references between the two objects, like so: | 246 // references between the two objects, like so: |
249 // | 247 // |
250 // { | 248 // { |
251 // scoped_refptr<MyFoo> a = new MyFoo(); | 249 // scoped_refptr<MyFoo> a = new MyFoo(); |
252 // scoped_refptr<MyFoo> b; | 250 // scoped_refptr<MyFoo> b; |
253 // | 251 // |
254 // b.swap(a); | 252 // b.swap(a); |
255 // // now, |b| references the MyFoo object, and |a| references NULL. | 253 // // now, |b| references the MyFoo object, and |a| references nullptr. |
256 // } | 254 // } |
257 // | 255 // |
258 // To make both |a| and |b| in the above example reference the same MyFoo | 256 // To make both |a| and |b| in the above example reference the same MyFoo |
259 // object, simply use the assignment operator: | 257 // object, simply use the assignment operator: |
260 // | 258 // |
261 // { | 259 // { |
262 // scoped_refptr<MyFoo> a = new MyFoo(); | 260 // scoped_refptr<MyFoo> a = new MyFoo(); |
263 // scoped_refptr<MyFoo> b; | 261 // scoped_refptr<MyFoo> b; |
264 // | 262 // |
265 // b = a; | 263 // b = a; |
266 // // now, |a| and |b| each own a reference to the same MyFoo object. | 264 // // now, |a| and |b| each own a reference to the same MyFoo object. |
267 // } | 265 // } |
268 // | 266 // |
269 template <class T> | 267 template <class T> |
270 class scoped_refptr { | 268 class scoped_refptr { |
271 public: | 269 public: |
272 typedef T element_type; | 270 typedef T element_type; |
273 | 271 |
274 scoped_refptr() : ptr_(NULL) { | 272 scoped_refptr() : ptr_(nullptr) { |
danakj
2016/10/25 20:29:18
i think do this at the site of defn
gab
2016/10/26 16:21:04
Done.
| |
275 } | 273 } |
276 | 274 |
277 scoped_refptr(T* p) : ptr_(p) { | 275 scoped_refptr(T* p) : ptr_(p) { |
278 if (ptr_) | 276 if (ptr_) |
279 AddRef(ptr_); | 277 AddRef(ptr_); |
280 } | 278 } |
281 | 279 |
282 // Copy constructor. | 280 // Copy constructor. |
283 scoped_refptr(const scoped_refptr<T>& r) : ptr_(r.ptr_) { | 281 scoped_refptr(const scoped_refptr<T>& r) : ptr_(r.ptr_) { |
284 if (ptr_) | 282 if (ptr_) |
(...skipping 22 matching lines...) Expand all Loading... | |
307 } | 305 } |
308 | 306 |
309 ~scoped_refptr() { | 307 ~scoped_refptr() { |
310 if (ptr_) | 308 if (ptr_) |
311 Release(ptr_); | 309 Release(ptr_); |
312 } | 310 } |
313 | 311 |
314 T* get() const { return ptr_; } | 312 T* get() const { return ptr_; } |
315 | 313 |
316 T& operator*() const { | 314 T& operator*() const { |
317 assert(ptr_ != NULL); | 315 assert(ptr_ != nullptr); |
318 return *ptr_; | 316 return *ptr_; |
319 } | 317 } |
320 | 318 |
321 T* operator->() const { | 319 T* operator->() const { |
322 assert(ptr_ != NULL); | 320 assert(ptr_ != nullptr); |
323 return ptr_; | 321 return ptr_; |
324 } | 322 } |
325 | 323 |
326 scoped_refptr<T>& operator=(T* p) { | 324 scoped_refptr<T>& operator=(T* p) { |
327 // AddRef first so that self assignment should work | 325 // AddRef first so that self assignment should work |
328 if (p) | 326 if (p) |
329 AddRef(p); | 327 AddRef(p); |
330 T* old_ptr = ptr_; | 328 T* old_ptr = ptr_; |
331 ptr_ = p; | 329 ptr_ = p; |
332 if (old_ptr) | 330 if (old_ptr) |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
375 bool operator!=(const scoped_refptr<U>& rhs) const { | 373 bool operator!=(const scoped_refptr<U>& rhs) const { |
376 return !operator==(rhs); | 374 return !operator==(rhs); |
377 } | 375 } |
378 | 376 |
379 template <typename U> | 377 template <typename U> |
380 bool operator<(const scoped_refptr<U>& rhs) const { | 378 bool operator<(const scoped_refptr<U>& rhs) const { |
381 return ptr_ < rhs.get(); | 379 return ptr_ < rhs.get(); |
382 } | 380 } |
383 | 381 |
384 protected: | 382 protected: |
385 T* ptr_; | 383 T* ptr_; |
danakj
2016/10/25 20:29:18
= nullptr
gab
2016/10/26 16:21:04
Done.
| |
386 | 384 |
387 private: | 385 private: |
388 // Friend required for move constructors that set r.ptr_ to null. | 386 // Friend required for move constructors that set r.ptr_ to null. |
389 template <typename U> | 387 template <typename U> |
390 friend class scoped_refptr; | 388 friend class scoped_refptr; |
391 | 389 |
392 // Non-inline helpers to allow: | 390 // Non-inline helpers to allow: |
393 // class Opaque; | 391 // class Opaque; |
394 // extern template class scoped_refptr<Opaque>; | 392 // extern template class scoped_refptr<Opaque>; |
395 // Otherwise the compiler will complain that Opaque is an incomplete type. | 393 // Otherwise the compiler will complain that Opaque is an incomplete type. |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
453 bool operator!=(std::nullptr_t null, const scoped_refptr<T>& rhs) { | 451 bool operator!=(std::nullptr_t null, const scoped_refptr<T>& rhs) { |
454 return !operator==(null, rhs); | 452 return !operator==(null, rhs); |
455 } | 453 } |
456 | 454 |
457 template <typename T> | 455 template <typename T> |
458 std::ostream& operator<<(std::ostream& out, const scoped_refptr<T>& p) { | 456 std::ostream& operator<<(std::ostream& out, const scoped_refptr<T>& p) { |
459 return out << p.get(); | 457 return out << p.get(); |
460 } | 458 } |
461 | 459 |
462 #endif // BASE_MEMORY_REF_COUNTED_H_ | 460 #endif // BASE_MEMORY_REF_COUNTED_H_ |
OLD | NEW |