| Index: base/memory/weak_ptr.h
|
| diff --git a/base/memory/weak_ptr.h b/base/memory/weak_ptr.h
|
| index 3544439dd3cafc9d8cc849a2cb4181cf70d2e947..f02362d908e71088b76fcae654cf7510f286166b 100644
|
| --- a/base/memory/weak_ptr.h
|
| +++ b/base/memory/weak_ptr.h
|
| @@ -81,8 +81,30 @@
|
|
|
| namespace base {
|
|
|
| -template <typename T> class SupportsWeakPtr;
|
| -template <typename T> class WeakPtr;
|
| +struct DefaultWeakPtrTraits {
|
| + template <typename T>
|
| + struct PointerHolder {
|
| + protected:
|
| + PointerHolder(T* ptr) : ptr_(ptr) {}
|
| + void reset() { ptr_ = nullptr; }
|
| + T* get() const { return ptr_; }
|
| +
|
| + private:
|
| + T* ptr_;
|
| + };
|
| +
|
| + template <typename T>
|
| + using PointerType = T*;
|
| +};
|
| +
|
| +template <typename T, typename Traits = DefaultWeakPtrTraits>
|
| +class SupportsWeakPtr;
|
| +
|
| +template <typename T, typename Pointer = DefaultWeakPtrTraits>
|
| +class WeakPtr;
|
| +
|
| +template <typename T, typename Pointer = DefaultWeakPtrTraits>
|
| +class WeakPtrFactory;
|
|
|
| namespace internal {
|
| // These classes are part of the WeakPtr implementation.
|
| @@ -164,35 +186,35 @@ class BASE_EXPORT WeakPtrBase {
|
| // otherwise get instantiated separately for each distinct instantiation of
|
| // SupportsWeakPtr<>.
|
| class SupportsWeakPtrBase {
|
| + private:
|
| + // This template function uses type inference to find a Base of Derived
|
| + // which is an instance of SupportsWeakPtr<Base>. We can then safely
|
| + // static_cast the Base* to a Derived*.
|
| + template <typename Derived, typename Base, typename Traits>
|
| + static WeakPtr<Derived, Traits> AsWeakPtrImpl(
|
| + Derived* t,
|
| + const SupportsWeakPtr<Base, Traits>&) {
|
| + WeakPtr<Base, Traits> ptr = t->Base::AsWeakPtr();
|
| + return WeakPtr<Derived, Traits>(ptr.ref_, static_cast<Derived*>(ptr.get()));
|
| + }
|
| +
|
| public:
|
| // A safe static downcast of a WeakPtr<Base> to WeakPtr<Derived>. This
|
| // conversion will only compile if there is exists a Base which inherits
|
| // from SupportsWeakPtr<Base>. See base::AsWeakPtr() below for a helper
|
| // function that makes calling this easier.
|
| - template<typename Derived>
|
| - static WeakPtr<Derived> StaticAsWeakPtr(Derived* t) {
|
| + template <typename Derived>
|
| + static auto StaticAsWeakPtr(Derived* t)
|
| + -> decltype(AsWeakPtrImpl<Derived>(t, *t)) {
|
| static_assert(
|
| std::is_base_of<internal::SupportsWeakPtrBase, Derived>::value,
|
| "AsWeakPtr argument must inherit from SupportsWeakPtr");
|
| return AsWeakPtrImpl<Derived>(t, *t);
|
| }
|
| -
|
| - private:
|
| - // This template function uses type inference to find a Base of Derived
|
| - // which is an instance of SupportsWeakPtr<Base>. We can then safely
|
| - // static_cast the Base* to a Derived*.
|
| - template <typename Derived, typename Base>
|
| - static WeakPtr<Derived> AsWeakPtrImpl(
|
| - Derived* t, const SupportsWeakPtr<Base>&) {
|
| - WeakPtr<Base> ptr = t->Base::AsWeakPtr();
|
| - return WeakPtr<Derived>(ptr.ref_, static_cast<Derived*>(ptr.ptr_));
|
| - }
|
| };
|
|
|
| } // namespace internal
|
|
|
| -template <typename T> class WeakPtrFactory;
|
| -
|
| // The WeakPtr class holds a weak reference to |T*|.
|
| //
|
| // This class is designed to be used like a normal pointer. You should always
|
| @@ -206,23 +228,30 @@ template <typename T> class WeakPtrFactory;
|
| // if (foo)
|
| // foo->method();
|
| //
|
| -template <typename T>
|
| -class WeakPtr : public internal::WeakPtrBase {
|
| - public:
|
| - WeakPtr() : ptr_(nullptr) {}
|
| +template <typename T, typename Traits>
|
| +class WeakPtr : public internal::WeakPtrBase,
|
| + public Traits::template PointerHolder<T> {
|
| + private:
|
| + using PointerHolder = typename Traits::template PointerHolder<T>;
|
|
|
| - WeakPtr(std::nullptr_t) : ptr_(nullptr) {}
|
| + public:
|
| + WeakPtr() : PointerHolder(nullptr) {}
|
| + WeakPtr(std::nullptr_t) : PointerHolder(nullptr) {}
|
|
|
| // Allow conversion from U to T provided U "is a" T. Note that this
|
| // is separate from the (implicit) copy and move constructors.
|
| - template <typename U>
|
| - WeakPtr(const WeakPtr<U>& other) : WeakPtrBase(other), ptr_(other.ptr_) {
|
| + template <typename U, typename OtherTraits>
|
| + WeakPtr(const WeakPtr<U, OtherTraits>& other)
|
| + : WeakPtrBase(other), PointerHolder(other.get()) {}
|
| + template <typename U, typename OtherTraits>
|
| + WeakPtr(WeakPtr<U, OtherTraits>&& other)
|
| + : WeakPtrBase(std::move(other)), PointerHolder(other.get()) {}
|
| +
|
| + T* get() const {
|
| + if (ref_.is_valid())
|
| + return PointerHolder::get();
|
| + return nullptr;
|
| }
|
| - template <typename U>
|
| - WeakPtr(WeakPtr<U>&& other)
|
| - : WeakPtrBase(std::move(other)), ptr_(other.ptr_) {}
|
| -
|
| - T* get() const { return ref_.is_valid() ? ptr_ : nullptr; }
|
|
|
| T& operator*() const {
|
| DCHECK(get() != nullptr);
|
| @@ -235,7 +264,7 @@ class WeakPtr : public internal::WeakPtrBase {
|
|
|
| void reset() {
|
| ref_ = internal::WeakReference();
|
| - ptr_ = nullptr;
|
| + PointerHolder::reset();
|
| }
|
|
|
| // Allow conditionals to test validity, e.g. if (weak_ptr) {...};
|
| @@ -243,35 +272,32 @@ class WeakPtr : public internal::WeakPtrBase {
|
|
|
| private:
|
| friend class internal::SupportsWeakPtrBase;
|
| - template <typename U> friend class WeakPtr;
|
| - friend class SupportsWeakPtr<T>;
|
| - friend class WeakPtrFactory<T>;
|
| -
|
| - WeakPtr(const internal::WeakReference& ref, T* ptr)
|
| - : WeakPtrBase(ref),
|
| - ptr_(ptr) {
|
| - }
|
| + template <typename, typename>
|
| + friend class WeakPtr;
|
| + friend class SupportsWeakPtr<T, Traits>;
|
| + friend class WeakPtrFactory<T, Traits>;
|
|
|
| // This pointer is only valid when ref_.is_valid() is true. Otherwise, its
|
| // value is undefined (as opposed to nullptr).
|
| - T* ptr_;
|
| + WeakPtr(const internal::WeakReference& ref, T* ptr)
|
| + : WeakPtrBase(ref), PointerHolder(std::move(ptr)) {}
|
| };
|
|
|
| // Allow callers to compare WeakPtrs against nullptr to test validity.
|
| -template <class T>
|
| -bool operator!=(const WeakPtr<T>& weak_ptr, std::nullptr_t) {
|
| +template <typename T, typename Traits>
|
| +bool operator!=(const WeakPtr<T, Traits>& weak_ptr, std::nullptr_t) {
|
| return !(weak_ptr == nullptr);
|
| }
|
| -template <class T>
|
| -bool operator!=(std::nullptr_t, const WeakPtr<T>& weak_ptr) {
|
| +template <typename T, typename Traits>
|
| +bool operator!=(std::nullptr_t, const WeakPtr<T, Traits>& weak_ptr) {
|
| return weak_ptr != nullptr;
|
| }
|
| -template <class T>
|
| -bool operator==(const WeakPtr<T>& weak_ptr, std::nullptr_t) {
|
| +template <typename T, typename Traits>
|
| +bool operator==(const WeakPtr<T, Traits>& weak_ptr, std::nullptr_t) {
|
| return weak_ptr.get() == nullptr;
|
| }
|
| -template <class T>
|
| -bool operator==(std::nullptr_t, const WeakPtr<T>& weak_ptr) {
|
| +template <typename T, typename Traits>
|
| +bool operator==(std::nullptr_t, const WeakPtr<T, Traits>& weak_ptr) {
|
| return weak_ptr == nullptr;
|
| }
|
|
|
| @@ -280,34 +306,36 @@ bool operator==(std::nullptr_t, const WeakPtr<T>& weak_ptr) {
|
| // need weak pointers within the implementation of a class. This class is also
|
| // useful when working with primitive types. For example, you could have a
|
| // WeakPtrFactory<bool> that is used to pass around a weak reference to a bool.
|
| -template <class T>
|
| -class WeakPtrFactory {
|
| +template <typename T, typename Traits>
|
| +class WeakPtrFactory : public Traits::template PointerHolder<T> {
|
| + private:
|
| + using PointerHolder = typename Traits::template PointerHolder<T>;
|
| +
|
| public:
|
| - explicit WeakPtrFactory(T* ptr) : ptr_(ptr) {
|
| - }
|
| + explicit WeakPtrFactory(T* ptr) : PointerHolder(ptr) {}
|
|
|
| - ~WeakPtrFactory() { ptr_ = nullptr; }
|
| + ~WeakPtrFactory() { PointerHolder::reset(); }
|
|
|
| - WeakPtr<T> GetWeakPtr() {
|
| - DCHECK(ptr_);
|
| - return WeakPtr<T>(weak_reference_owner_.GetRef(), ptr_);
|
| + WeakPtr<T, Traits> GetWeakPtr() {
|
| + DCHECK(PointerHolder::get());
|
| + return WeakPtr<T, Traits>(weak_reference_owner_.GetRef(),
|
| + PointerHolder::get());
|
| }
|
|
|
| // Call this method to invalidate all existing weak pointers.
|
| void InvalidateWeakPtrs() {
|
| - DCHECK(ptr_);
|
| + DCHECK(PointerHolder::get());
|
| weak_reference_owner_.Invalidate();
|
| }
|
|
|
| // Call this method to determine if any weak pointers exist.
|
| bool HasWeakPtrs() const {
|
| - DCHECK(ptr_);
|
| + DCHECK(PointerHolder::get());
|
| return weak_reference_owner_.HasRefs();
|
| }
|
|
|
| private:
|
| internal::WeakReferenceOwner weak_reference_owner_;
|
| - T* ptr_;
|
| DISALLOW_IMPLICIT_CONSTRUCTORS(WeakPtrFactory);
|
| };
|
|
|
| @@ -316,13 +344,14 @@ class WeakPtrFactory {
|
| // pointers. However, since SupportsWeakPtr's destructor won't invalidate
|
| // weak pointers to the class until after the derived class' members have been
|
| // destroyed, its use can lead to subtle use-after-destroy issues.
|
| -template <class T>
|
| +template <typename T, typename Traits>
|
| class SupportsWeakPtr : public internal::SupportsWeakPtrBase {
|
| public:
|
| SupportsWeakPtr() {}
|
|
|
| - WeakPtr<T> AsWeakPtr() {
|
| - return WeakPtr<T>(weak_reference_owner_.GetRef(), static_cast<T*>(this));
|
| + WeakPtr<T, Traits> AsWeakPtr() {
|
| + return WeakPtr<T, Traits>(weak_reference_owner_.GetRef(),
|
| + static_cast<T*>(this));
|
| }
|
|
|
| protected:
|
| @@ -352,7 +381,8 @@ class SupportsWeakPtr : public internal::SupportsWeakPtrBase {
|
| // base::WeakPtr<Derived> ptr = derived.AsWeakPtr(); // Fails.
|
|
|
| template <typename Derived>
|
| -WeakPtr<Derived> AsWeakPtr(Derived* t) {
|
| +auto AsWeakPtr(Derived* t)
|
| + -> decltype(internal::SupportsWeakPtrBase::StaticAsWeakPtr<Derived>(t)) {
|
| return internal::SupportsWeakPtrBase::StaticAsWeakPtr<Derived>(t);
|
| }
|
|
|
|
|