Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1573)

Unified Diff: base/memory/weak_ptr.h

Issue 2371663002: Introduce an injection point to configure the internal pointer of WeakPtr
Patch Set: fix Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | base/memory/weak_ptr_unittest.nc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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);
}
« no previous file with comments | « no previous file | base/memory/weak_ptr_unittest.nc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698