| 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 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 scoped_refptr() {} | 272 scoped_refptr() {} |
| 273 | 273 |
| 274 scoped_refptr(T* p) : ptr_(p) { | 274 scoped_refptr(T* p) : ptr_(p), ptr_caller_(&PtrCallerImpl) { |
| 275 if (ptr_) | 275 if (ptr_) |
| 276 AddRef(ptr_); | 276 ptr_caller_(ptr_, PtrCall::AddRef); |
| 277 } | 277 } |
| 278 | 278 |
| 279 // Copy constructor. | 279 // Copy constructor. |
| 280 scoped_refptr(const scoped_refptr<T>& r) : ptr_(r.ptr_) { | 280 scoped_refptr(const scoped_refptr<T>& r) |
| 281 : ptr_(r.ptr_), ptr_caller_(r.ptr_caller_) { |
| 281 if (ptr_) | 282 if (ptr_) |
| 282 AddRef(ptr_); | 283 ptr_caller_(ptr_, PtrCall::AddRef); |
| 283 } | 284 } |
| 284 | 285 |
| 285 // Copy conversion constructor. | 286 // Copy conversion constructor. |
| 286 template <typename U, | 287 template <typename U, |
| 287 typename = typename std::enable_if< | 288 typename = typename std::enable_if< |
| 288 std::is_convertible<U*, T*>::value>::type> | 289 std::is_convertible<U*, T*>::value>::type> |
| 289 scoped_refptr(const scoped_refptr<U>& r) : ptr_(r.get()) { | 290 scoped_refptr(const scoped_refptr<U>& r) |
| 291 : ptr_(r.get()), ptr_caller_(&PtrCallerImpl) { |
| 290 if (ptr_) | 292 if (ptr_) |
| 291 AddRef(ptr_); | 293 ptr_caller_(ptr_, PtrCall::AddRef); |
| 292 } | 294 } |
| 293 | 295 |
| 294 // Move constructor. This is required in addition to the conversion | 296 // Move constructor. This is required in addition to the conversion |
| 295 // constructor below in order for clang to warn about pessimizing moves. | 297 // constructor below in order for clang to warn about pessimizing moves. |
| 296 scoped_refptr(scoped_refptr&& r) : ptr_(r.get()) { r.ptr_ = nullptr; } | 298 scoped_refptr(scoped_refptr&& r) : ptr_(r.get()), ptr_caller_(r.ptr_caller_) { |
| 299 r.ptr_ = nullptr; |
| 300 } |
| 297 | 301 |
| 298 // Move conversion constructor. | 302 // Move conversion constructor. |
| 299 template <typename U, | 303 template <typename U, |
| 300 typename = typename std::enable_if< | 304 typename = typename std::enable_if< |
| 301 std::is_convertible<U*, T*>::value>::type> | 305 std::is_convertible<U*, T*>::value>::type> |
| 302 scoped_refptr(scoped_refptr<U>&& r) : ptr_(r.get()) { | 306 scoped_refptr(scoped_refptr<U>&& r) |
| 307 : ptr_(r.get()), ptr_caller_(&PtrCallerImpl) { |
| 303 r.ptr_ = nullptr; | 308 r.ptr_ = nullptr; |
| 304 } | 309 } |
| 305 | 310 |
| 306 ~scoped_refptr() { | 311 ~scoped_refptr() { |
| 307 if (ptr_) | 312 if (ptr_) |
| 308 Release(ptr_); | 313 ptr_caller_(ptr_, PtrCall::Release); |
| 309 } | 314 } |
| 310 | 315 |
| 311 T* get() const { return ptr_; } | 316 T* get() const { return ptr_; } |
| 312 | 317 |
| 313 T& operator*() const { | 318 T& operator*() const { |
| 314 assert(ptr_ != nullptr); | 319 assert(ptr_ != nullptr); |
| 315 return *ptr_; | 320 return *ptr_; |
| 316 } | 321 } |
| 317 | 322 |
| 318 T* operator->() const { | 323 T* operator->() const { |
| 319 assert(ptr_ != nullptr); | 324 assert(ptr_ != nullptr); |
| 320 return ptr_; | 325 return ptr_; |
| 321 } | 326 } |
| 322 | 327 |
| 323 scoped_refptr<T>& operator=(T* p) { | 328 scoped_refptr<T>& operator=(T* p) { |
| 324 // AddRef first so that self assignment should work | 329 Assign(p, &PtrCallerImpl); |
| 325 if (p) | |
| 326 AddRef(p); | |
| 327 T* old_ptr = ptr_; | |
| 328 ptr_ = p; | |
| 329 if (old_ptr) | |
| 330 Release(old_ptr); | |
| 331 return *this; | 330 return *this; |
| 332 } | 331 } |
| 333 | 332 |
| 334 scoped_refptr<T>& operator=(const scoped_refptr<T>& r) { | 333 scoped_refptr<T>& operator=(const scoped_refptr<T>& r) { |
| 335 return *this = r.ptr_; | 334 Assign(r.ptr_, r.ptr_caller_); |
| 335 return *this; |
| 336 } | 336 } |
| 337 | 337 |
| 338 template <typename U> | 338 template <typename U> |
| 339 scoped_refptr<T>& operator=(const scoped_refptr<U>& r) { | 339 scoped_refptr<T>& operator=(const scoped_refptr<U>& r) { |
| 340 return *this = r.get(); | 340 Assign(r.get(), &PtrCallerImpl); |
| 341 return *this; |
| 341 } | 342 } |
| 342 | 343 |
| 343 scoped_refptr<T>& operator=(scoped_refptr<T>&& r) { | 344 scoped_refptr<T>& operator=(scoped_refptr<T>&& r) { |
| 344 scoped_refptr<T>(std::move(r)).swap(*this); | 345 scoped_refptr<T>(std::move(r)).swap(*this); |
| 345 return *this; | 346 return *this; |
| 346 } | 347 } |
| 347 | 348 |
| 348 template <typename U> | 349 template <typename U> |
| 349 scoped_refptr<T>& operator=(scoped_refptr<U>&& r) { | 350 scoped_refptr<T>& operator=(scoped_refptr<U>&& r) { |
| 350 scoped_refptr<T>(std::move(r)).swap(*this); | 351 scoped_refptr<T>(std::move(r)).swap(*this); |
| 351 return *this; | 352 return *this; |
| 352 } | 353 } |
| 353 | 354 |
| 354 void swap(T** pp) { | 355 void swap(T** pp) { |
| 355 T* p = ptr_; | 356 T* p = ptr_; |
| 356 ptr_ = *pp; | 357 ptr_ = *pp; |
| 358 ptr_caller_ = &PtrCallerImpl; |
| 357 *pp = p; | 359 *pp = p; |
| 358 } | 360 } |
| 359 | 361 |
| 360 void swap(scoped_refptr<T>& r) { | 362 void swap(scoped_refptr<T>& r) { |
| 361 swap(&r.ptr_); | 363 std::swap(ptr_, r.ptr_); |
| 364 std::swap(ptr_caller_, r.ptr_caller_); |
| 362 } | 365 } |
| 363 | 366 |
| 364 explicit operator bool() const { return ptr_ != nullptr; } | 367 explicit operator bool() const { return ptr_ != nullptr; } |
| 365 | 368 |
| 366 template <typename U> | 369 template <typename U> |
| 367 bool operator==(const scoped_refptr<U>& rhs) const { | 370 bool operator==(const scoped_refptr<U>& rhs) const { |
| 368 return ptr_ == rhs.get(); | 371 return ptr_ == rhs.get(); |
| 369 } | 372 } |
| 370 | 373 |
| 371 template <typename U> | 374 template <typename U> |
| 372 bool operator!=(const scoped_refptr<U>& rhs) const { | 375 bool operator!=(const scoped_refptr<U>& rhs) const { |
| 373 return !operator==(rhs); | 376 return !operator==(rhs); |
| 374 } | 377 } |
| 375 | 378 |
| 376 template <typename U> | 379 template <typename U> |
| 377 bool operator<(const scoped_refptr<U>& rhs) const { | 380 bool operator<(const scoped_refptr<U>& rhs) const { |
| 378 return ptr_ < rhs.get(); | 381 return ptr_ < rhs.get(); |
| 379 } | 382 } |
| 380 | 383 |
| 381 protected: | 384 protected: |
| 385 enum class PtrCall { AddRef, Release }; |
| 386 using PtrCallerFunction = void (*)(T* ptr, PtrCall call); |
| 387 |
| 388 static void PtrCallerImpl(T* ptr, PtrCall call) { |
| 389 switch (call) { |
| 390 case PtrCall::AddRef: |
| 391 ptr->AddRef(); |
| 392 break; |
| 393 case PtrCall::Release: |
| 394 ptr->Release(); |
| 395 break; |
| 396 } |
| 397 } |
| 398 |
| 382 T* ptr_ = nullptr; | 399 T* ptr_ = nullptr; |
| 400 PtrCallerFunction ptr_caller_ = nullptr; |
| 383 | 401 |
| 384 private: | 402 private: |
| 385 // Friend required for move constructors that set r.ptr_ to null. | |
| 386 template <typename U> | 403 template <typename U> |
| 387 friend class scoped_refptr; | 404 friend class scoped_refptr; |
| 388 | 405 |
| 389 // Non-inline helpers to allow: | 406 void Assign(T* p, PtrCallerFunction caller) { |
| 390 // class Opaque; | 407 // AddRef first so that self assignment should work |
| 391 // extern template class scoped_refptr<Opaque>; | 408 if (p) |
| 392 // Otherwise the compiler will complain that Opaque is an incomplete type. | 409 caller(p, PtrCall::AddRef); |
| 393 static void AddRef(T* ptr); | 410 T* old_ptr = ptr_; |
| 394 static void Release(T* ptr); | 411 PtrCallerFunction old_caller = ptr_caller_; |
| 412 ptr_ = p; |
| 413 ptr_caller_ = caller; |
| 414 if (old_ptr) |
| 415 old_caller(old_ptr, PtrCall::Release); |
| 416 // Release above can potentially delete this object |
| 417 } |
| 395 }; | 418 }; |
| 396 | 419 |
| 397 // static | |
| 398 template <typename T> | |
| 399 void scoped_refptr<T>::AddRef(T* ptr) { | |
| 400 ptr->AddRef(); | |
| 401 } | |
| 402 | |
| 403 // static | |
| 404 template <typename T> | |
| 405 void scoped_refptr<T>::Release(T* ptr) { | |
| 406 ptr->Release(); | |
| 407 } | |
| 408 | |
| 409 // Handy utility for creating a scoped_refptr<T> out of a T* explicitly without | 420 // Handy utility for creating a scoped_refptr<T> out of a T* explicitly without |
| 410 // having to retype all the template arguments | 421 // having to retype all the template arguments |
| 411 template <typename T> | 422 template <typename T> |
| 412 scoped_refptr<T> make_scoped_refptr(T* t) { | 423 scoped_refptr<T> make_scoped_refptr(T* t) { |
| 413 return scoped_refptr<T>(t); | 424 return scoped_refptr<T>(t); |
| 414 } | 425 } |
| 415 | 426 |
| 416 template <typename T, typename U> | 427 template <typename T, typename U> |
| 417 bool operator==(const scoped_refptr<T>& lhs, const U* rhs) { | 428 bool operator==(const scoped_refptr<T>& lhs, const U* rhs) { |
| 418 return lhs.get() == rhs; | 429 return lhs.get() == rhs; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 452 bool operator!=(std::nullptr_t null, const scoped_refptr<T>& rhs) { | 463 bool operator!=(std::nullptr_t null, const scoped_refptr<T>& rhs) { |
| 453 return !operator==(null, rhs); | 464 return !operator==(null, rhs); |
| 454 } | 465 } |
| 455 | 466 |
| 456 template <typename T> | 467 template <typename T> |
| 457 std::ostream& operator<<(std::ostream& out, const scoped_refptr<T>& p) { | 468 std::ostream& operator<<(std::ostream& out, const scoped_refptr<T>& p) { |
| 458 return out << p.get(); | 469 return out << p.get(); |
| 459 } | 470 } |
| 460 | 471 |
| 461 #endif // BASE_MEMORY_REF_COUNTED_H_ | 472 #endif // BASE_MEMORY_REF_COUNTED_H_ |
| OLD | NEW |