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 #include "base/macros.h" 15 #ifndef NDEBUG 16 #include "base/logging.h" 17 #endif 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: HasOneRef()27 bool HasOneRef() const { return ref_count_ == 1; } 28 29 protected: RefCountedBase()30 RefCountedBase() 31 : ref_count_(0) 32 #ifndef NDEBUG 33 , in_dtor_(false) 34 #endif 35 { 36 } 37 ~RefCountedBase()38 ~RefCountedBase() { 39 #ifndef NDEBUG 40 DCHECK(in_dtor_) << "RefCounted object deleted without calling Release()"; 41 #endif 42 } 43 44 AddRef()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. Release()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 non-public, 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: RefCounted()126 RefCounted() {} 127 AddRef()128 void AddRef() const { 129 subtle::RefCountedBase::AddRef(); 130 } 131 Release()132 void Release() const { 133 if (subtle::RefCountedBase::Release()) { 134 delete static_cast<const T*>(this); 135 } 136 } 137 138 protected: ~RefCounted()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 { DestructDefaultRefCountedThreadSafeTraits152 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: RefCountedThreadSafe()176 RefCountedThreadSafe() {} 177 AddRef()178 void AddRef() const { 179 subtle::RefCountedThreadSafeBase::AddRef(); 180 } 181 Release()182 void Release() const { 183 if (subtle::RefCountedThreadSafeBase::Release()) { 184 Traits::Destruct(static_cast<const T*>(this)); 185 } 186 } 187 188 protected: ~RefCountedThreadSafe()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 public: 269 typedef T element_type; 270 271 scoped_refptr() : ptr_(NULL) { 272 } 273 274 scoped_refptr(T* p) : ptr_(p) { 275 if (ptr_) 276 AddRef(ptr_); 277 } 278 279 // Copy constructor. 280 scoped_refptr(const scoped_refptr<T>& r) : ptr_(r.ptr_) { 281 if (ptr_) 282 AddRef(ptr_); 283 } 284 285 // Copy conversion constructor. 286 template <typename U> 287 scoped_refptr(const scoped_refptr<U>& r) : ptr_(r.get()) { 288 if (ptr_) 289 AddRef(ptr_); 290 } 291 292 // Move constructor. This is required in addition to the conversion 293 // constructor below in order for clang to warn about pessimizing moves. 294 scoped_refptr(scoped_refptr&& r) : ptr_(r.get()) { r.ptr_ = nullptr; } 295 296 // Move conversion constructor. 297 template <typename U> 298 scoped_refptr(scoped_refptr<U>&& r) : ptr_(r.get()) { 299 r.ptr_ = nullptr; 300 } 301 302 ~scoped_refptr() { 303 if (ptr_) 304 Release(ptr_); 305 } 306 307 T* get() const { return ptr_; } 308 309 T& operator*() const { 310 assert(ptr_ != NULL); 311 return *ptr_; 312 } 313 314 T* operator->() const { 315 assert(ptr_ != NULL); 316 return ptr_; 317 } 318 319 scoped_refptr<T>& operator=(T* p) { 320 // AddRef first so that self assignment should work 321 if (p) 322 AddRef(p); 323 T* old_ptr = ptr_; 324 ptr_ = p; 325 if (old_ptr) 326 Release(old_ptr); 327 return *this; 328 } 329 330 scoped_refptr<T>& operator=(const scoped_refptr<T>& r) { 331 return *this = r.ptr_; 332 } 333 334 template <typename U> 335 scoped_refptr<T>& operator=(const scoped_refptr<U>& r) { 336 return *this = r.get(); 337 } 338 339 scoped_refptr<T>& operator=(scoped_refptr<T>&& r) { 340 scoped_refptr<T>(std::move(r)).swap(*this); 341 return *this; 342 } 343 344 template <typename U> 345 scoped_refptr<T>& operator=(scoped_refptr<U>&& r) { 346 scoped_refptr<T>(std::move(r)).swap(*this); 347 return *this; 348 } 349 350 void swap(T** pp) { 351 T* p = ptr_; 352 ptr_ = *pp; 353 *pp = p; 354 } 355 356 void swap(scoped_refptr<T>& r) { 357 swap(&r.ptr_); 358 } 359 360 private: 361 template <typename U> friend class scoped_refptr; 362 363 // Allow scoped_refptr<T> to be used in boolean expressions, but not 364 // implicitly convertible to a real bool (which is dangerous). 365 // 366 // Note that this trick is only safe when the == and != operators 367 // are declared explicitly, as otherwise "refptr1 == refptr2" 368 // will compile but do the wrong thing (i.e., convert to Testable 369 // and then do the comparison). 370 typedef T* scoped_refptr::*Testable; 371 372 public: 373 operator Testable() const { return ptr_ ? &scoped_refptr::ptr_ : nullptr; } 374 375 template <typename U> 376 bool operator==(const scoped_refptr<U>& rhs) const { 377 return ptr_ == rhs.get(); 378 } 379 380 template <typename U> 381 bool operator!=(const scoped_refptr<U>& rhs) const { 382 return !operator==(rhs); 383 } 384 385 template <typename U> 386 bool operator<(const scoped_refptr<U>& rhs) const { 387 return ptr_ < rhs.get(); 388 } 389 390 protected: 391 T* ptr_; 392 393 private: 394 // Non-inline helpers to allow: 395 // class Opaque; 396 // extern template class scoped_refptr<Opaque>; 397 // Otherwise the compiler will complain that Opaque is an incomplete type. 398 static void AddRef(T* ptr); 399 static void Release(T* ptr); 400 }; 401 402 template <typename T> 403 void scoped_refptr<T>::AddRef(T* ptr) { 404 ptr->AddRef(); 405 } 406 407 template <typename T> 408 void scoped_refptr<T>::Release(T* ptr) { 409 ptr->Release(); 410 } 411 412 // Handy utility for creating a scoped_refptr<T> out of a T* explicitly without 413 // having to retype all the template arguments 414 template <typename T> 415 scoped_refptr<T> make_scoped_refptr(T* t) { 416 return scoped_refptr<T>(t); 417 } 418 419 // Temporary operator overloads to facilitate the transition. See 420 // https://crbug.com/110610. 421 template <typename T, typename U> 422 bool operator==(const scoped_refptr<T>& lhs, const U* rhs) { 423 return lhs.get() == rhs; 424 } 425 426 template <typename T, typename U> 427 bool operator==(const T* lhs, const scoped_refptr<U>& rhs) { 428 return lhs == rhs.get(); 429 } 430 431 template <typename T, typename U> 432 bool operator!=(const scoped_refptr<T>& lhs, const U* rhs) { 433 return !operator==(lhs, rhs); 434 } 435 436 template <typename T, typename U> 437 bool operator!=(const T* lhs, const scoped_refptr<U>& rhs) { 438 return !operator==(lhs, rhs); 439 } 440 441 template <typename T> 442 std::ostream& operator<<(std::ostream& out, const scoped_refptr<T>& p) { 443 return out << p.get(); 444 } 445 446 #endif // BASE_MEMORY_REF_COUNTED_H_ 447