| 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) { |
| 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 120 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 |