| 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> | 
| (...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 262 // | 262 // | 
| 263 //     b = a; | 263 //     b = a; | 
| 264 //     // 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. | 
| 265 //   } | 265 //   } | 
| 266 // | 266 // | 
| 267 template <class T> | 267 template <class T> | 
| 268 class scoped_refptr { | 268 class scoped_refptr { | 
| 269  public: | 269  public: | 
| 270   typedef T element_type; | 270   typedef T element_type; | 
| 271 | 271 | 
|  | 272   // RefCounted<T> or RefCountedThreadSafe<T> depending on the type implemented | 
|  | 273   // by T (or T itself for RefCountedThreadSafe<T, CustomTraits> and the rare | 
|  | 274   // use case of classes providing their own AddRef/Release methods and being | 
|  | 275   // stored in a scoped_refptr). | 
|  | 276   using RefCountedType = typename std::conditional< | 
|  | 277       std::is_convertible<T*, base::RefCounted<T>*>::value, | 
|  | 278       base::RefCounted<T>, | 
|  | 279       typename std::conditional< | 
|  | 280           std::is_convertible<T*, base::RefCountedThreadSafe<T>*>::value, | 
|  | 281           base::RefCountedThreadSafe<T>, | 
|  | 282           T>::type>::type; | 
|  | 283 | 
| 272   scoped_refptr() = default; | 284   scoped_refptr() = default; | 
| 273 | 285 | 
| 274   scoped_refptr(T* p) : ptr_(p) { | 286   scoped_refptr(T* p) : ptr_(p) { | 
| 275     if (ptr_) | 287     if (ref_) | 
| 276       AddRef(ptr_); | 288       AddRef(ref_); | 
| 277   } | 289   } | 
| 278 | 290 | 
| 279   // Copy constructor. | 291   // Copy constructor. | 
| 280   scoped_refptr(const scoped_refptr<T>& r) : ptr_(r.ptr_) { | 292   scoped_refptr(const scoped_refptr<T>& r) : ptr_(r.ptr_) { | 
| 281     if (ptr_) | 293     if (ref_) | 
| 282       AddRef(ptr_); | 294       AddRef(ref_); | 
| 283   } | 295   } | 
| 284 | 296 | 
| 285   // Copy conversion constructor. | 297   // Copy conversion constructor. | 
| 286   template <typename U, | 298   template <typename U, | 
| 287             typename = typename std::enable_if< | 299             typename = typename std::enable_if< | 
| 288                 std::is_convertible<U*, T*>::value>::type> | 300                 std::is_convertible<U*, T*>::value>::type> | 
| 289   scoped_refptr(const scoped_refptr<U>& r) : ptr_(r.get()) { | 301   scoped_refptr(const scoped_refptr<U>& r) : ptr_(r.get()) { | 
| 290     if (ptr_) | 302     if (ref_) | 
| 291       AddRef(ptr_); | 303       AddRef(ref_); | 
| 292   } | 304   } | 
| 293 | 305 | 
| 294   // Move constructor. This is required in addition to the conversion | 306   // Move constructor. This is required in addition to the conversion | 
| 295   // constructor below in order for clang to warn about pessimizing moves. | 307   // constructor below in order for clang to warn about pessimizing moves. | 
| 296   scoped_refptr(scoped_refptr&& r) : ptr_(r.get()) { r.ptr_ = nullptr; } | 308   scoped_refptr(scoped_refptr&& r) : ptr_(r.get()) { r.ptr_ = nullptr; } | 
| 297 | 309 | 
| 298   // Move conversion constructor. | 310   // Move conversion constructor. | 
| 299   template <typename U, | 311   template <typename U, | 
| 300             typename = typename std::enable_if< | 312             typename = typename std::enable_if< | 
| 301                 std::is_convertible<U*, T*>::value>::type> | 313                 std::is_convertible<U*, T*>::value>::type> | 
| 302   scoped_refptr(scoped_refptr<U>&& r) : ptr_(r.get()) { | 314   scoped_refptr(scoped_refptr<U>&& r) : ptr_(r.get()) { | 
| 303     r.ptr_ = nullptr; | 315     r.ptr_ = nullptr; | 
| 304   } | 316   } | 
| 305 | 317 | 
| 306   ~scoped_refptr() { | 318   ~scoped_refptr() { | 
| 307     if (ptr_) | 319     if (ref_) | 
| 308       Release(ptr_); | 320       Release(ref_); | 
| 309   } | 321   } | 
| 310 | 322 | 
| 311   T* get() const { return ptr_; } | 323   T* get() const { return ptr_; } | 
| 312 | 324 | 
| 313   T& operator*() const { | 325   T& operator*() const { | 
| 314     assert(ptr_ != nullptr); | 326     assert(ptr_ != nullptr); | 
| 315     return *ptr_; | 327     return *ptr_; | 
| 316   } | 328   } | 
| 317 | 329 | 
| 318   T* operator->() const { | 330   T* operator->() const { | 
| 319     assert(ptr_ != nullptr); | 331     assert(ptr_ != nullptr); | 
| 320     return ptr_; | 332     return ptr_; | 
| 321   } | 333   } | 
| 322 | 334 | 
| 323   scoped_refptr<T>& operator=(T* p) { | 335   scoped_refptr<T>& operator=(T* p) { | 
| 324     // AddRef first so that self assignment should work | 336     // AddRef first so that self assignment should work | 
|  | 337     // Note: This AddRef() can't use the |ref_| trick, so assigning from a naked | 
|  | 338     // pointer requires the assignor to have the full definition of |T|. | 
| 325     if (p) | 339     if (p) | 
| 326       AddRef(p); | 340       AddRef(p); | 
| 327     T* old_ptr = ptr_; | 341     const RefCountedType* old_ref = ref_; | 
| 328     ptr_ = p; | 342     ptr_ = p; | 
| 329     if (old_ptr) | 343     if (old_ref) | 
| 330       Release(old_ptr); | 344       Release(old_ref); | 
| 331     return *this; | 345     return *this; | 
| 332   } | 346   } | 
| 333 | 347 | 
| 334   scoped_refptr<T>& operator=(const scoped_refptr<T>& r) { | 348   scoped_refptr<T>& operator=(const scoped_refptr<T>& r) { | 
| 335     return *this = r.ptr_; | 349     return *this = r.ptr_; | 
| 336   } | 350   } | 
| 337 | 351 | 
| 338   template <typename U> | 352   template <typename U> | 
| 339   scoped_refptr<T>& operator=(const scoped_refptr<U>& r) { | 353   scoped_refptr<T>& operator=(const scoped_refptr<U>& r) { | 
| 340     return *this = r.get(); | 354     return *this = r.get(); | 
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 372   bool operator!=(const scoped_refptr<U>& rhs) const { | 386   bool operator!=(const scoped_refptr<U>& rhs) const { | 
| 373     return !operator==(rhs); | 387     return !operator==(rhs); | 
| 374   } | 388   } | 
| 375 | 389 | 
| 376   template <typename U> | 390   template <typename U> | 
| 377   bool operator<(const scoped_refptr<U>& rhs) const { | 391   bool operator<(const scoped_refptr<U>& rhs) const { | 
| 378     return ptr_ < rhs.get(); | 392     return ptr_ < rhs.get(); | 
| 379   } | 393   } | 
| 380 | 394 | 
| 381  protected: | 395  protected: | 
|  | 396   //FIXME need to update |ref_| when updating |ptr_|. | 
| 382   T* ptr_ = nullptr; | 397   T* ptr_ = nullptr; | 
| 383 | 398 | 
|  | 399   // |ref_| merely points to |ptr_| but the type checking is done when | 
|  | 400   // scoped_refptr is constructed instead of when it's used, this allows | 
|  | 401   // callsites that merely do: | 
|  | 402   //     void PassRefToFoo(Foo* foo, scoped_refptr<T> t) { | 
|  | 403   //       foo->TakeRef(std::move(t)); | 
|  | 404   //     } | 
|  | 405   // to compile without the full definition of |T| as they can perform | 
|  | 406   // AddRef/Release operations on it without having to know that it implements | 
|  | 407   // RefCountedInterface. | 
|  | 408   //FIXME: This still doesn't work because template instantiations still need to | 
|  | 409   //know the full type to derive |RefCountedType|... | 
|  | 410   const RefCountedType* ref_ = ptr_; | 
|  | 411 | 
| 384  private: | 412  private: | 
| 385   // Friend required for move constructors that set r.ptr_ to null. | 413   // Friend required for move constructors that set r.ptr_ to null. | 
| 386   template <typename U> | 414   template <typename U> | 
| 387   friend class scoped_refptr; | 415   friend class scoped_refptr; | 
| 388 | 416 | 
| 389   // Non-inline helpers to allow: | 417   // Non-inline helpers to allow: | 
| 390   //     class Opaque; | 418   //     class Opaque; | 
| 391   //     extern template class scoped_refptr<Opaque>; | 419   //     extern template class scoped_refptr<Opaque>; | 
| 392   // Otherwise the compiler will complain that Opaque is an incomplete type. | 420   // Otherwise the compiler will complain that Opaque is an incomplete type. | 
| 393   static void AddRef(T* ptr); | 421   static void AddRef(const RefCountedType* ref_type); | 
| 394   static void Release(T* ptr); | 422   static void Release(const RefCountedType* ref_type); | 
| 395 }; | 423 }; | 
| 396 | 424 | 
|  | 425 // static | 
| 397 template <typename T> | 426 template <typename T> | 
| 398 void scoped_refptr<T>::AddRef(T* ptr) { | 427 void scoped_refptr<T>::AddRef( | 
| 399   ptr->AddRef(); | 428     const scoped_refptr<T>::RefCountedType* ref_type) { | 
|  | 429   ref_type->AddRef(); | 
| 400 } | 430 } | 
| 401 | 431 | 
|  | 432 // static | 
| 402 template <typename T> | 433 template <typename T> | 
| 403 void scoped_refptr<T>::Release(T* ptr) { | 434 void scoped_refptr<T>::Release( | 
| 404   ptr->Release(); | 435     const scoped_refptr<T>::RefCountedType* ref_type) { | 
|  | 436   ref_type->Release(); | 
| 405 } | 437 } | 
| 406 | 438 | 
| 407 // Handy utility for creating a scoped_refptr<T> out of a T* explicitly without | 439 // Handy utility for creating a scoped_refptr<T> out of a T* explicitly without | 
| 408 // having to retype all the template arguments | 440 // having to retype all the template arguments | 
| 409 template <typename T> | 441 template <typename T> | 
| 410 scoped_refptr<T> make_scoped_refptr(T* t) { | 442 scoped_refptr<T> make_scoped_refptr(T* t) { | 
| 411   return scoped_refptr<T>(t); | 443   return scoped_refptr<T>(t); | 
| 412 } | 444 } | 
| 413 | 445 | 
| 414 template <typename T, typename U> | 446 template <typename T, typename U> | 
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 450 bool operator!=(std::nullptr_t null, const scoped_refptr<T>& rhs) { | 482 bool operator!=(std::nullptr_t null, const scoped_refptr<T>& rhs) { | 
| 451   return !operator==(null, rhs); | 483   return !operator==(null, rhs); | 
| 452 } | 484 } | 
| 453 | 485 | 
| 454 template <typename T> | 486 template <typename T> | 
| 455 std::ostream& operator<<(std::ostream& out, const scoped_refptr<T>& p) { | 487 std::ostream& operator<<(std::ostream& out, const scoped_refptr<T>& p) { | 
| 456   return out << p.get(); | 488   return out << p.get(); | 
| 457 } | 489 } | 
| 458 | 490 | 
| 459 #endif  // BASE_MEMORY_REF_COUNTED_H_ | 491 #endif  // BASE_MEMORY_REF_COUNTED_H_ | 
| OLD | NEW | 
|---|