| Index: base/memory/ref_counted.h
|
| diff --git a/base/memory/ref_counted.h b/base/memory/ref_counted.h
|
| index 6a689388d9d2d93ea0f1624c2316bdbadf044907..acbe67583221c5dad76393d2abab835f94acb7f3 100644
|
| --- a/base/memory/ref_counted.h
|
| +++ b/base/memory/ref_counted.h
|
| @@ -269,17 +269,29 @@ class scoped_refptr {
|
| public:
|
| typedef T element_type;
|
|
|
| + // RefCounted<T> or RefCountedThreadSafe<T> depending on the type implemented
|
| + // by T (or T itself for RefCountedThreadSafe<T, CustomTraits> and the rare
|
| + // use case of classes providing their own AddRef/Release methods and being
|
| + // stored in a scoped_refptr).
|
| + using RefCountedType = typename std::conditional<
|
| + std::is_convertible<T*, base::RefCounted<T>*>::value,
|
| + base::RefCounted<T>,
|
| + typename std::conditional<
|
| + std::is_convertible<T*, base::RefCountedThreadSafe<T>*>::value,
|
| + base::RefCountedThreadSafe<T>,
|
| + T>::type>::type;
|
| +
|
| scoped_refptr() = default;
|
|
|
| scoped_refptr(T* p) : ptr_(p) {
|
| - if (ptr_)
|
| - AddRef(ptr_);
|
| + if (ref_)
|
| + AddRef(ref_);
|
| }
|
|
|
| // Copy constructor.
|
| scoped_refptr(const scoped_refptr<T>& r) : ptr_(r.ptr_) {
|
| - if (ptr_)
|
| - AddRef(ptr_);
|
| + if (ref_)
|
| + AddRef(ref_);
|
| }
|
|
|
| // Copy conversion constructor.
|
| @@ -287,8 +299,8 @@ class scoped_refptr {
|
| typename = typename std::enable_if<
|
| std::is_convertible<U*, T*>::value>::type>
|
| scoped_refptr(const scoped_refptr<U>& r) : ptr_(r.get()) {
|
| - if (ptr_)
|
| - AddRef(ptr_);
|
| + if (ref_)
|
| + AddRef(ref_);
|
| }
|
|
|
| // Move constructor. This is required in addition to the conversion
|
| @@ -304,8 +316,8 @@ class scoped_refptr {
|
| }
|
|
|
| ~scoped_refptr() {
|
| - if (ptr_)
|
| - Release(ptr_);
|
| + if (ref_)
|
| + Release(ref_);
|
| }
|
|
|
| T* get() const { return ptr_; }
|
| @@ -322,12 +334,14 @@ class scoped_refptr {
|
|
|
| scoped_refptr<T>& operator=(T* p) {
|
| // AddRef first so that self assignment should work
|
| + // Note: This AddRef() can't use the |ref_| trick, so assigning from a naked
|
| + // pointer requires the assignor to have the full definition of |T|.
|
| if (p)
|
| AddRef(p);
|
| - T* old_ptr = ptr_;
|
| + const RefCountedType* old_ref = ref_;
|
| ptr_ = p;
|
| - if (old_ptr)
|
| - Release(old_ptr);
|
| + if (old_ref)
|
| + Release(old_ref);
|
| return *this;
|
| }
|
|
|
| @@ -379,8 +393,22 @@ class scoped_refptr {
|
| }
|
|
|
| protected:
|
| + //FIXME need to update |ref_| when updating |ptr_|.
|
| T* ptr_ = nullptr;
|
|
|
| + // |ref_| merely points to |ptr_| but the type checking is done when
|
| + // scoped_refptr is constructed instead of when it's used, this allows
|
| + // callsites that merely do:
|
| + // void PassRefToFoo(Foo* foo, scoped_refptr<T> t) {
|
| + // foo->TakeRef(std::move(t));
|
| + // }
|
| + // to compile without the full definition of |T| as they can perform
|
| + // AddRef/Release operations on it without having to know that it implements
|
| + // RefCountedInterface.
|
| + //FIXME: This still doesn't work because template instantiations still need to
|
| + //know the full type to derive |RefCountedType|...
|
| + const RefCountedType* ref_ = ptr_;
|
| +
|
| private:
|
| // Friend required for move constructors that set r.ptr_ to null.
|
| template <typename U>
|
| @@ -390,18 +418,22 @@ class scoped_refptr {
|
| // 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);
|
| + static void AddRef(const RefCountedType* ref_type);
|
| + static void Release(const RefCountedType* ref_type);
|
| };
|
|
|
| +// static
|
| template <typename T>
|
| -void scoped_refptr<T>::AddRef(T* ptr) {
|
| - ptr->AddRef();
|
| +void scoped_refptr<T>::AddRef(
|
| + const scoped_refptr<T>::RefCountedType* ref_type) {
|
| + ref_type->AddRef();
|
| }
|
|
|
| +// static
|
| template <typename T>
|
| -void scoped_refptr<T>::Release(T* ptr) {
|
| - ptr->Release();
|
| +void scoped_refptr<T>::Release(
|
| + const scoped_refptr<T>::RefCountedType* ref_type) {
|
| + ref_type->Release();
|
| }
|
|
|
| // Handy utility for creating a scoped_refptr<T> out of a T* explicitly without
|
|
|