| Index: base/memory/ref_counted.h
|
| diff --git a/base/memory/ref_counted.h b/base/memory/ref_counted.h
|
| index 960c8a28453122a5e00a2cb72d5f420e7b642f15..c9ba42401ed43976aa3e0317d72906cc81e612ab 100644
|
| --- a/base/memory/ref_counted.h
|
| +++ b/base/memory/ref_counted.h
|
| @@ -271,41 +271,46 @@ class scoped_refptr {
|
|
|
| scoped_refptr() {}
|
|
|
| - scoped_refptr(T* p) : ptr_(p) {
|
| + scoped_refptr(T* p) : ptr_(p), ptr_caller_(&PtrCallerImpl) {
|
| if (ptr_)
|
| - AddRef(ptr_);
|
| + ptr_caller_(ptr_, PtrCall::AddRef);
|
| }
|
|
|
| // Copy constructor.
|
| - scoped_refptr(const scoped_refptr<T>& r) : ptr_(r.ptr_) {
|
| + scoped_refptr(const scoped_refptr<T>& r)
|
| + : ptr_(r.ptr_), ptr_caller_(r.ptr_caller_) {
|
| if (ptr_)
|
| - AddRef(ptr_);
|
| + ptr_caller_(ptr_, PtrCall::AddRef);
|
| }
|
|
|
| // Copy conversion constructor.
|
| template <typename U,
|
| typename = typename std::enable_if<
|
| std::is_convertible<U*, T*>::value>::type>
|
| - scoped_refptr(const scoped_refptr<U>& r) : ptr_(r.get()) {
|
| + scoped_refptr(const scoped_refptr<U>& r)
|
| + : ptr_(r.get()), ptr_caller_(&PtrCallerImpl) {
|
| if (ptr_)
|
| - AddRef(ptr_);
|
| + ptr_caller_(ptr_, PtrCall::AddRef);
|
| }
|
|
|
| // Move constructor. This is required in addition to the conversion
|
| // constructor below in order for clang to warn about pessimizing moves.
|
| - scoped_refptr(scoped_refptr&& r) : ptr_(r.get()) { r.ptr_ = nullptr; }
|
| + scoped_refptr(scoped_refptr&& r) : ptr_(r.get()), ptr_caller_(r.ptr_caller_) {
|
| + r.ptr_ = nullptr;
|
| + }
|
|
|
| // Move conversion constructor.
|
| template <typename U,
|
| typename = typename std::enable_if<
|
| std::is_convertible<U*, T*>::value>::type>
|
| - scoped_refptr(scoped_refptr<U>&& r) : ptr_(r.get()) {
|
| + scoped_refptr(scoped_refptr<U>&& r)
|
| + : ptr_(r.get()), ptr_caller_(&PtrCallerImpl) {
|
| r.ptr_ = nullptr;
|
| }
|
|
|
| ~scoped_refptr() {
|
| if (ptr_)
|
| - Release(ptr_);
|
| + ptr_caller_(ptr_, PtrCall::Release);
|
| }
|
|
|
| T* get() const { return ptr_; }
|
| @@ -321,23 +326,19 @@ class scoped_refptr {
|
| }
|
|
|
| scoped_refptr<T>& operator=(T* p) {
|
| - // AddRef first so that self assignment should work
|
| - if (p)
|
| - AddRef(p);
|
| - T* old_ptr = ptr_;
|
| - ptr_ = p;
|
| - if (old_ptr)
|
| - Release(old_ptr);
|
| + Assign(p, &PtrCallerImpl);
|
| return *this;
|
| }
|
|
|
| scoped_refptr<T>& operator=(const scoped_refptr<T>& r) {
|
| - return *this = r.ptr_;
|
| + Assign(r.ptr_, r.ptr_caller_);
|
| + return *this;
|
| }
|
|
|
| template <typename U>
|
| scoped_refptr<T>& operator=(const scoped_refptr<U>& r) {
|
| - return *this = r.get();
|
| + Assign(r.get(), &PtrCallerImpl);
|
| + return *this;
|
| }
|
|
|
| scoped_refptr<T>& operator=(scoped_refptr<T>&& r) {
|
| @@ -354,11 +355,13 @@ class scoped_refptr {
|
| void swap(T** pp) {
|
| T* p = ptr_;
|
| ptr_ = *pp;
|
| + ptr_caller_ = &PtrCallerImpl;
|
| *pp = p;
|
| }
|
|
|
| void swap(scoped_refptr<T>& r) {
|
| - swap(&r.ptr_);
|
| + std::swap(ptr_, r.ptr_);
|
| + std::swap(ptr_caller_, r.ptr_caller_);
|
| }
|
|
|
| explicit operator bool() const { return ptr_ != nullptr; }
|
| @@ -379,33 +382,41 @@ class scoped_refptr {
|
| }
|
|
|
| protected:
|
| + enum class PtrCall { AddRef, Release };
|
| + using PtrCallerFunction = void (*)(T* ptr, PtrCall call);
|
| +
|
| + static void PtrCallerImpl(T* ptr, PtrCall call) {
|
| + switch (call) {
|
| + case PtrCall::AddRef:
|
| + ptr->AddRef();
|
| + break;
|
| + case PtrCall::Release:
|
| + ptr->Release();
|
| + break;
|
| + }
|
| + }
|
| +
|
| T* ptr_ = nullptr;
|
| + PtrCallerFunction ptr_caller_ = nullptr;
|
|
|
| private:
|
| - // Friend required for move constructors that set r.ptr_ to null.
|
| template <typename U>
|
| friend class scoped_refptr;
|
|
|
| - // Non-inline helpers to allow:
|
| - // class Opaque;
|
| - // extern template class scoped_refptr<Opaque>;
|
| - // Otherwise the compiler will complain that Opaque is an incomplete type.
|
| - static void AddRef(T* ptr);
|
| - static void Release(T* ptr);
|
| + void Assign(T* p, PtrCallerFunction caller) {
|
| + // AddRef first so that self assignment should work
|
| + if (p)
|
| + caller(p, PtrCall::AddRef);
|
| + T* old_ptr = ptr_;
|
| + PtrCallerFunction old_caller = ptr_caller_;
|
| + ptr_ = p;
|
| + ptr_caller_ = caller;
|
| + if (old_ptr)
|
| + old_caller(old_ptr, PtrCall::Release);
|
| + // Release above can potentially delete this object
|
| + }
|
| };
|
|
|
| -// static
|
| -template <typename T>
|
| -void scoped_refptr<T>::AddRef(T* ptr) {
|
| - ptr->AddRef();
|
| -}
|
| -
|
| -// static
|
| -template <typename T>
|
| -void scoped_refptr<T>::Release(T* ptr) {
|
| - ptr->Release();
|
| -}
|
| -
|
| // Handy utility for creating a scoped_refptr<T> out of a T* explicitly without
|
| // having to retype all the template arguments
|
| template <typename T>
|
|
|