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 <stddef.h> 9 10 #include <cassert> 11 #include <iosfwd> 12 #include <type_traits> 13 14 #include "base/atomic_ref_count.h" 15 #include "base/base_export.h" 16 #include "base/compiler_specific.h" 17 #include "base/macros.h" 18 #ifndef NDEBUG 19 #include "base/logging.h" 20 #endif 21 #include "base/threading/thread_collision_warner.h" 22 #include "build/build_config.h" 23 24 namespace base { 25 26 namespace subtle { 27 28 class BASE_EXPORT RefCountedBase { 29 public: HasOneRef()30 bool HasOneRef() const { return ref_count_ == 1; } 31 32 protected: RefCountedBase()33 RefCountedBase() 34 : ref_count_(0) 35 #ifndef NDEBUG 36 , in_dtor_(false) 37 #endif 38 { 39 } 40 ~RefCountedBase()41 ~RefCountedBase() { 42 #ifndef NDEBUG 43 DCHECK(in_dtor_) << "RefCounted object deleted without calling Release()"; 44 #endif 45 } 46 47 AddRef()48 void AddRef() const { 49 // TODO(maruel): Add back once it doesn't assert 500 times/sec. 50 // Current thread books the critical section "AddRelease" 51 // without release it. 52 // DFAKE_SCOPED_LOCK_THREAD_LOCKED(add_release_); 53 #ifndef NDEBUG 54 DCHECK(!in_dtor_); 55 #endif 56 ++ref_count_; 57 } 58 59 // Returns true if the object should self-delete. Release()60 bool Release() const { 61 // TODO(maruel): Add back once it doesn't assert 500 times/sec. 62 // Current thread books the critical section "AddRelease" 63 // without release it. 64 // DFAKE_SCOPED_LOCK_THREAD_LOCKED(add_release_); 65 #ifndef NDEBUG 66 DCHECK(!in_dtor_); 67 #endif 68 if (--ref_count_ == 0) { 69 #ifndef NDEBUG 70 in_dtor_ = true; 71 #endif 72 return true; 73 } 74 return false; 75 } 76 77 private: 78 mutable int ref_count_; 79 #ifndef NDEBUG 80 mutable bool in_dtor_; 81 #endif 82 83 DFAKE_MUTEX(add_release_); 84 85 DISALLOW_COPY_AND_ASSIGN(RefCountedBase); 86 }; 87 88 class BASE_EXPORT RefCountedThreadSafeBase { 89 public: 90 bool HasOneRef() const; 91 92 protected: 93 RefCountedThreadSafeBase(); 94 ~RefCountedThreadSafeBase(); 95 96 void AddRef() const; 97 98 // Returns true if the object should self-delete. 99 bool Release() const; 100 101 private: 102 mutable AtomicRefCount ref_count_; 103 #ifndef NDEBUG 104 mutable bool in_dtor_; 105 #endif 106 107 DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafeBase); 108 }; 109 110 } // namespace subtle 111 112 // 113 // 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 115 // class from it like so: 116 // 117 // class MyFoo : public base::RefCounted<MyFoo> { 118 // ... 119 // private: 120 // friend class base::RefCounted<MyFoo>; 121 // ~MyFoo(); 122 // }; 123 // 124 // You should always make your destructor non-public, to avoid any code deleting 125 // the object accidently while there are references to it. 126 template <class T> 127 class RefCounted : public subtle::RefCountedBase { 128 public: RefCounted()129 RefCounted() {} 130 AddRef()131 void AddRef() const { 132 subtle::RefCountedBase::AddRef(); 133 } 134 Release()135 void Release() const { 136 if (subtle::RefCountedBase::Release()) { 137 delete static_cast<const T*>(this); 138 } 139 } 140 141 protected: ~RefCounted()142 ~RefCounted() {} 143 144 private: 145 DISALLOW_COPY_AND_ASSIGN(RefCounted<T>); 146 }; 147 148 // Forward declaration. 149 template <class T, typename Traits> class RefCountedThreadSafe; 150 151 // Default traits for RefCountedThreadSafe<T>. Deletes the object when its ref 152 // count reaches 0. Overload to delete it on a different thread etc. 153 template<typename T> 154 struct DefaultRefCountedThreadSafeTraits { DestructDefaultRefCountedThreadSafeTraits155 static void Destruct(const T* x) { 156 // Delete through RefCountedThreadSafe to make child classes only need to be 157 // friend with RefCountedThreadSafe instead of this struct, which is an 158 // implementation detail. 159 RefCountedThreadSafe<T, 160 DefaultRefCountedThreadSafeTraits>::DeleteInternal(x); 161 } 162 }; 163 164 // 165 // A thread-safe variant of RefCounted<T> 166 // 167 // class MyFoo : public base::RefCountedThreadSafe<MyFoo> { 168 // ... 169 // }; 170 // 171 // 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. 173 // private: 174 // friend class base::RefCountedThreadSafe<MyFoo>; 175 // ~MyFoo(); 176 template <class T, typename Traits = DefaultRefCountedThreadSafeTraits<T> > 177 class RefCountedThreadSafe : public subtle::RefCountedThreadSafeBase { 178 public: RefCountedThreadSafe()179 RefCountedThreadSafe() {} 180 AddRef()181 void AddRef() const { 182 subtle::RefCountedThreadSafeBase::AddRef(); 183 } 184 Release()185 void Release() const { 186 if (subtle::RefCountedThreadSafeBase::Release()) { 187 Traits::Destruct(static_cast<const T*>(this)); 188 } 189 } 190 191 protected: ~RefCountedThreadSafe()192 ~RefCountedThreadSafe() {} 193 194 private: 195 friend struct DefaultRefCountedThreadSafeTraits<T>; 196 static void DeleteInternal(const T* x) { delete x; } 197 198 DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafe); 199 }; 200 201 // 202 // A thread-safe wrapper for some piece of data so we can place other 203 // things in scoped_refptrs<>. 204 // 205 template<typename T> 206 class RefCountedData 207 : public base::RefCountedThreadSafe< base::RefCountedData<T> > { 208 public: 209 RefCountedData() : data() {} 210 RefCountedData(const T& in_value) : data(in_value) {} 211 212 T data; 213 214 private: 215 friend class base::RefCountedThreadSafe<base::RefCountedData<T> >; 216 ~RefCountedData() {} 217 }; 218 219 } // namespace base 220 221 // 222 // 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 224 // avoid common memory leaks caused by forgetting to Release an object 225 // reference. Sample usage: 226 // 227 // class MyFoo : public RefCounted<MyFoo> { 228 // ... 229 // }; 230 // 231 // void some_function() { 232 // scoped_refptr<MyFoo> foo = new MyFoo(); 233 // foo->Method(param); 234 // // |foo| is released when this function returns 235 // } 236 // 237 // void some_other_function() { 238 // scoped_refptr<MyFoo> foo = new MyFoo(); 239 // ... 240 // foo = NULL; // explicitly releases |foo| 241 // ... 242 // if (foo) 243 // foo->Method(param); 244 // } 245 // 246 // 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 248 // references between the two objects, like so: 249 // 250 // { 251 // scoped_refptr<MyFoo> a = new MyFoo(); 252 // scoped_refptr<MyFoo> b; 253 // 254 // b.swap(a); 255 // // now, |b| references the MyFoo object, and |a| references NULL. 256 // } 257 // 258 // To make both |a| and |b| in the above example reference the same MyFoo 259 // object, simply use the assignment operator: 260 // 261 // { 262 // scoped_refptr<MyFoo> a = new MyFoo(); 263 // scoped_refptr<MyFoo> b; 264 // 265 // b = a; 266 // // now, |a| and |b| each own a reference to the same MyFoo object. 267 // } 268 // 269 template <class T> 270 class scoped_refptr { 271 public: 272 typedef T element_type; 273 274 scoped_refptr() : ptr_(NULL) { 275 } 276 277 scoped_refptr(T* p) : ptr_(p) { 278 if (ptr_) 279 AddRef(ptr_); 280 } 281 282 // Copy constructor. 283 scoped_refptr(const scoped_refptr<T>& r) : ptr_(r.ptr_) { 284 if (ptr_) 285 AddRef(ptr_); 286 } 287 288 // Copy conversion constructor. 289 template <typename U, 290 typename = typename std::enable_if< 291 std::is_convertible<U*, T*>::value>::type> 292 scoped_refptr(const scoped_refptr<U>& r) : ptr_(r.get()) { 293 if (ptr_) 294 AddRef(ptr_); 295 } 296 297 // Move constructor. This is required in addition to the conversion 298 // constructor below in order for clang to warn about pessimizing moves. 299 scoped_refptr(scoped_refptr&& r) : ptr_(r.get()) { r.ptr_ = nullptr; } 300 301 // Move conversion constructor. 302 template <typename U, 303 typename = typename std::enable_if< 304 std::is_convertible<U*, T*>::value>::type> 305 scoped_refptr(scoped_refptr<U>&& r) : ptr_(r.get()) { 306 r.ptr_ = nullptr; 307 } 308 309 ~scoped_refptr() { 310 if (ptr_) 311 Release(ptr_); 312 } 313 314 T* get() const { return ptr_; } 315 316 T& operator*() const { 317 assert(ptr_ != NULL); 318 return *ptr_; 319 } 320 321 T* operator->() const { 322 assert(ptr_ != NULL); 323 return ptr_; 324 } 325 326 scoped_refptr<T>& operator=(T* p) { 327 // AddRef first so that self assignment should work 328 if (p) 329 AddRef(p); 330 T* old_ptr = ptr_; 331 ptr_ = p; 332 if (old_ptr) 333 Release(old_ptr); 334 return *this; 335 } 336 337 scoped_refptr<T>& operator=(const scoped_refptr<T>& r) { 338 return *this = r.ptr_; 339 } 340 341 template <typename U> 342 scoped_refptr<T>& operator=(const scoped_refptr<U>& r) { 343 return *this = r.get(); 344 } 345 346 scoped_refptr<T>& operator=(scoped_refptr<T>&& r) { 347 scoped_refptr<T>(std::move(r)).swap(*this); 348 return *this; 349 } 350 351 template <typename U> 352 scoped_refptr<T>& operator=(scoped_refptr<U>&& r) { 353 scoped_refptr<T>(std::move(r)).swap(*this); 354 return *this; 355 } 356 357 void swap(T** pp) { 358 T* p = ptr_; 359 ptr_ = *pp; 360 *pp = p; 361 } 362 363 void swap(scoped_refptr<T>& r) { 364 swap(&r.ptr_); 365 } 366 367 explicit operator bool() const { return 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 // Friend required for move constructors that set r.ptr_ to null. 389 template <typename U> 390 friend class scoped_refptr; 391 392 // Non-inline helpers to allow: 393 // class Opaque; 394 // extern template class scoped_refptr<Opaque>; 395 // Otherwise the compiler will complain that Opaque is an incomplete type. 396 static void AddRef(T* ptr); 397 static void Release(T* ptr); 398 }; 399 400 template <typename T> 401 void scoped_refptr<T>::AddRef(T* ptr) { 402 ptr->AddRef(); 403 } 404 405 template <typename T> 406 void scoped_refptr<T>::Release(T* ptr) { 407 ptr->Release(); 408 } 409 410 // Handy utility for creating a scoped_refptr<T> out of a T* explicitly without 411 // having to retype all the template arguments 412 template <typename T> 413 scoped_refptr<T> make_scoped_refptr(T* t) { 414 return scoped_refptr<T>(t); 415 } 416 417 template <typename T, typename U> 418 bool operator==(const scoped_refptr<T>& lhs, const U* rhs) { 419 return lhs.get() == rhs; 420 } 421 422 template <typename T, typename U> 423 bool operator==(const T* lhs, const scoped_refptr<U>& rhs) { 424 return lhs == rhs.get(); 425 } 426 427 template <typename T> 428 bool operator==(const scoped_refptr<T>& lhs, std::nullptr_t) { 429 return !static_cast<bool>(lhs); 430 } 431 432 template <typename T> 433 bool operator==(std::nullptr_t, const scoped_refptr<T>& rhs) { 434 return !static_cast<bool>(rhs); 435 } 436 437 template <typename T, typename U> 438 bool operator!=(const scoped_refptr<T>& lhs, const U* rhs) { 439 return !operator==(lhs, rhs); 440 } 441 442 template <typename T, typename U> 443 bool operator!=(const T* lhs, const scoped_refptr<U>& rhs) { 444 return !operator==(lhs, rhs); 445 } 446 447 template <typename T> 448 bool operator!=(const scoped_refptr<T>& lhs, std::nullptr_t null) { 449 return !operator==(lhs, null); 450 } 451 452 template <typename T> 453 bool operator!=(std::nullptr_t null, const scoped_refptr<T>& rhs) { 454 return !operator==(null, rhs); 455 } 456 457 template <typename T> 458 std::ostream& operator<<(std::ostream& out, const scoped_refptr<T>& p) { 459 return out << p.get(); 460 } 461 462 #endif // BASE_MEMORY_REF_COUNTED_H_ 463