Chromium Code Reviews| Index: base/memory/weak_ptr.h |
| diff --git a/base/memory/weak_ptr.h b/base/memory/weak_ptr.h |
| index 06e65669954007c0c940410c0a6bd0adf5b44008..fbeeb20f60b42973536442bf1e45b70c459fd183 100644 |
| --- a/base/memory/weak_ptr.h |
| +++ b/base/memory/weak_ptr.h |
| @@ -90,27 +90,17 @@ namespace internal { |
| class BASE_EXPORT WeakReference { |
| public: |
| - |
| - class BASE_EXPORT NewFlag { |
| + // Although Flag is bound to a specific SequencedTaskRunner, it may be |
| + // deleted from another via base::WeakPtr::~WeakPtr(). |
| + class BASE_EXPORT Flag : public RefCountedThreadSafe<Flag> { |
| public: |
| - constexpr static uintptr_t kTrueMask = ~static_cast<uintptr_t>(0); |
| - |
| - static NewFlag *NullFlag() { return &g_null_flag; } |
| - NewFlag() : is_valid_(kTrueMask), ref_count_(0) { |
| -#if DCHECK_IS_ON() |
| - // Flags only become bound when checked for validity, or invalidated, |
| - // so that we can check that later validity/invalidation operations on |
| - // the same Flag take place on the same sequenced thread. |
| - sequence_checker_.DetachFromSequence(); |
| -#endif |
| - } |
| + Flag(); |
| + static Flag* nullFlag(); |
| void Invalidate() { |
| #if DCHECK_IS_ON() |
| - if (this == NullFlag()) { |
| - DCHECK(!is_valid_); |
| + if (this == nullFlag()) |
| return; |
| - } |
| // The flag being invalidated with a single ref implies that there are no |
| // weak pointers in existence. Allow deletion on other thread in this case. |
| DCHECK(sequence_checker_.CalledOnValidSequence() || HasOneRef()) |
| @@ -118,12 +108,11 @@ class BASE_EXPORT WeakReference { |
| #endif |
| is_valid_ = 0; |
| } |
| - |
| uintptr_t IsValid() const { |
| #if DCHECK_IS_ON() |
| - if (this == NullFlag()) { |
| + if (this == nullFlag()) { |
| DCHECK(!is_valid_); |
| - return false; |
| + return 0; |
| } |
| DCHECK(sequence_checker_.CalledOnValidSequence()) |
| << "WeakPtrs must be checked on the same sequenced thread."; |
| @@ -131,52 +120,24 @@ class BASE_EXPORT WeakReference { |
| return is_valid_; |
| } |
| - uintptr_t NumRefs() const { return ref_count_; } |
| - |
| - void AddRef() const { AtomicRefCountInc(&ref_count_); } |
| - void Release() const { |
| - if (!AtomicRefCountDec(&ref_count_)) |
| - delete this; |
| - } |
| - |
| private: |
| - ~NewFlag() = default; |
| + friend class base::RefCountedThreadSafe<Flag>; |
| + |
| enum NullFlagTag { kNullFlagTag }; |
| -#if DCHECK_IS_ON() |
| - NewFlag(NullFlagTag); |
| -#else |
| - constexpr NewFlag(NullFlagTag); |
| -#endif |
| + Flag(NullFlagTag); |
| - static NewFlag g_null_flag; |
| + ~Flag(); |
| uintptr_t is_valid_; |
| - mutable AtomicRefCount ref_count_; |
| #if DCHECK_IS_ON() |
| + // Even if SequenceChecker is an empty class in non-dcheck builds, it still |
| + // takes up space in the class. |
| SequenceChecker sequence_checker_; |
| #endif |
| }; |
| - // Although Flag is bound to a specific SequencedTaskRunner, it may be |
| - // deleted from another via base::WeakPtr::~WeakPtr(). |
| - class BASE_EXPORT Flag : public RefCountedThreadSafe<Flag> { |
| - public: |
| - Flag(); |
| - |
| - void Invalidate(); |
| - bool IsValid() const; |
| - |
| - private: |
| - friend class base::RefCountedThreadSafe<Flag>; |
| - |
| - ~Flag(); |
| - |
| - SequenceChecker sequence_checker_; |
| - bool is_valid_; |
| - }; |
| - |
| WeakReference(); |
| - explicit WeakReference(/*const Flag* flag,*/ const NewFlag* new_flag); |
| + explicit WeakReference(const Flag* flag); |
| ~WeakReference(); |
| WeakReference(WeakReference&& other); |
| @@ -184,11 +145,12 @@ class BASE_EXPORT WeakReference { |
| WeakReference& operator=(WeakReference&& other) = default; |
| WeakReference& operator=(const WeakReference& other) = default; |
| - uintptr_t is_valid() const { return new_flag_->IsValid(); } |
| + uintptr_t is_valid() const { return flag_->IsValid(); } |
| private: |
| - //scoped_refptr<const Flag> flag_; |
| - scoped_refptr<const NewFlag> new_flag_; |
| + // Note: To avoid null-checks, flag_ always points to either Flag::nullFlag() |
| + // or some other object. |
| + scoped_refptr<const Flag> flag_; |
| }; |
| class BASE_EXPORT WeakReferenceOwner { |
| @@ -198,21 +160,12 @@ class BASE_EXPORT WeakReferenceOwner { |
| WeakReference GetRef() const; |
| - bool HasRefs() const { |
| - return (new_flag_->IsValid() & new_flag_->NumRefs()) > 1; |
| - |
| -#if 0 |
|
Nico
2017/06/27 22:05:41
This looks like your diffbase might be off?
hans
2017/06/27 22:09:50
Yeah, something is not right here :-(
|
| - return new_flag_ != WeakReference::NewFlag::NullFlag() && |
| - !new_flag_->HasOneRef(); |
| -#endif |
| - //return flag_.get() && !flag_->HasOneRef(); |
| - } |
| + bool HasRefs() const { return flag_->IsValid() && !flag_->HasOneRef(); } |
| void Invalidate(); |
| private: |
| - //mutable scoped_refptr<WeakReference::Flag> flag_; |
| - mutable scoped_refptr<WeakReference::NewFlag> new_flag_; |
| + mutable scoped_refptr<WeakReference::Flag> flag_; |
| }; |
| // This class simplifies the implementation of WeakPtr's type conversion |
| @@ -352,11 +305,7 @@ bool operator==(std::nullptr_t, const WeakPtr<T>& weak_ptr) { |
| return weak_ptr == nullptr; |
| } |
| -// A class may be composed of a WeakPtrFactory and thereby |
| -// control how it exposes weak pointers to itself. This is helpful if you only |
| -// 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. |
| +namespace internal { |
| class BASE_EXPORT WeakPtrFactoryBase { |
| protected: |
| WeakPtrFactoryBase(uintptr_t ptr); |
| @@ -364,17 +313,25 @@ class BASE_EXPORT WeakPtrFactoryBase { |
| internal::WeakReferenceOwner weak_reference_owner_; |
| uintptr_t ptr_; |
| }; |
| +} // namespace internal |
| +// A class may be composed of a WeakPtrFactory and thereby |
| +// control how it exposes weak pointers to itself. This is helpful if you only |
| +// 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 : public WeakPtrFactoryBase { |
| +class WeakPtrFactory : public internal::WeakPtrFactoryBase { |
| public: |
| - explicit WeakPtrFactory(T* ptr) : WeakPtrFactoryBase(reinterpret_cast<uintptr_t>(ptr)) { } |
| + explicit WeakPtrFactory(T* ptr) |
| + : WeakPtrFactoryBase(reinterpret_cast<uintptr_t>(ptr)) {} |
| ~WeakPtrFactory() {} |
| WeakPtr<T> GetWeakPtr() { |
| DCHECK(ptr_); |
| - return WeakPtr<T>(weak_reference_owner_.GetRef(), reinterpret_cast<T*>(ptr_)); |
| + return WeakPtr<T>(weak_reference_owner_.GetRef(), |
| + reinterpret_cast<T*>(ptr_)); |
| } |
| // Call this method to invalidate all existing weak pointers. |