| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // Weak pointers are pointers to an object that do not affect its lifetime, | 5 // Weak pointers are pointers to an object that do not affect its lifetime, |
| 6 // and which may be invalidated (i.e. reset to nullptr) by the object, or its | 6 // and which may be invalidated (i.e. reset to nullptr) by the object, or its |
| 7 // owner, at any time, most commonly when the object is about to be deleted. | 7 // owner, at any time, most commonly when the object is about to be deleted. |
| 8 | 8 |
| 9 // Weak pointers are useful when an object needs to be accessed safely by one | 9 // Weak pointers are useful when an object needs to be accessed safely by one |
| 10 // or more objects other than its owner, and those callers can cope with the | 10 // or more objects other than its owner, and those callers can cope with the |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 89 // DO NOT USE THESE CLASSES DIRECTLY YOURSELF. | 89 // DO NOT USE THESE CLASSES DIRECTLY YOURSELF. |
| 90 | 90 |
| 91 class BASE_EXPORT WeakReference { | 91 class BASE_EXPORT WeakReference { |
| 92 public: | 92 public: |
| 93 // Although Flag is bound to a specific SequencedTaskRunner, it may be | 93 // Although Flag is bound to a specific SequencedTaskRunner, it may be |
| 94 // deleted from another via base::WeakPtr::~WeakPtr(). | 94 // deleted from another via base::WeakPtr::~WeakPtr(). |
| 95 class BASE_EXPORT Flag : public RefCountedThreadSafe<Flag> { | 95 class BASE_EXPORT Flag : public RefCountedThreadSafe<Flag> { |
| 96 public: | 96 public: |
| 97 Flag(); | 97 Flag(); |
| 98 | 98 |
| 99 // Get a pointer to the "Null Flag", a sentinel object used by WeakReference | 99 void Invalidate(); |
| 100 // objects that don't point to a valid Flag, either because they're default | 100 bool IsValid() const; |
| 101 // constructed or because they have been invalidated. This can be used like | |
| 102 // any other Flag object, but it is invalidated already from the start, and | |
| 103 // its refcount will never reach zero. | |
| 104 static Flag* NullFlag(); | |
| 105 | |
| 106 void Invalidate() { | |
| 107 #if DCHECK_IS_ON() | |
| 108 if (this == NullFlag()) { | |
| 109 // The Null Flag does not participate in the sequence checks below. | |
| 110 // Since its state never changes, it can be accessed from any thread. | |
| 111 DCHECK(!is_valid_); | |
| 112 return; | |
| 113 } | |
| 114 // The flag being invalidated with a single ref implies that there are no | |
| 115 // weak pointers in existence. Allow deletion on other thread in this | |
| 116 // case. | |
| 117 DCHECK(sequence_checker_.CalledOnValidSequence() || HasOneRef()) | |
| 118 << "WeakPtrs must be invalidated on the same sequenced thread."; | |
| 119 #endif | |
| 120 is_valid_ = 0; | |
| 121 } | |
| 122 | |
| 123 // Returns a pointer-sized bitmask of all 1s if valid or all 0s otherwise. | |
| 124 uintptr_t IsValid() const { | |
| 125 #if DCHECK_IS_ON() | |
| 126 if (this == NullFlag()) { | |
| 127 // The Null Flag does not participate in the sequence checks below. | |
| 128 // Since its state never changes, it can be accessed from any thread. | |
| 129 DCHECK(!is_valid_); | |
| 130 return 0; | |
| 131 } | |
| 132 DCHECK(sequence_checker_.CalledOnValidSequence()) | |
| 133 << "WeakPtrs must be checked on the same sequenced thread."; | |
| 134 #endif | |
| 135 return is_valid_; | |
| 136 } | |
| 137 | 101 |
| 138 private: | 102 private: |
| 139 friend class base::RefCountedThreadSafe<Flag>; | 103 friend class base::RefCountedThreadSafe<Flag>; |
| 140 | 104 |
| 141 enum NullFlagTag { kNullFlagTag }; | |
| 142 Flag(NullFlagTag); | |
| 143 | |
| 144 ~Flag(); | 105 ~Flag(); |
| 145 | 106 |
| 146 uintptr_t is_valid_; | |
| 147 #if DCHECK_IS_ON() | |
| 148 // Even if SequenceChecker is an empty class in non-dcheck builds, it still | |
| 149 // takes up space in the class. | |
| 150 SequenceChecker sequence_checker_; | 107 SequenceChecker sequence_checker_; |
| 151 #endif | 108 bool is_valid_; |
| 152 }; | 109 }; |
| 153 | 110 |
| 154 WeakReference(); | 111 WeakReference(); |
| 155 explicit WeakReference(const Flag* flag); | 112 explicit WeakReference(const Flag* flag); |
| 156 ~WeakReference(); | 113 ~WeakReference(); |
| 157 | 114 |
| 158 WeakReference(WeakReference&& other); | 115 WeakReference(WeakReference&& other); |
| 159 WeakReference(const WeakReference& other); | 116 WeakReference(const WeakReference& other); |
| 160 WeakReference& operator=(WeakReference&& other) = default; | 117 WeakReference& operator=(WeakReference&& other) = default; |
| 161 WeakReference& operator=(const WeakReference& other) = default; | 118 WeakReference& operator=(const WeakReference& other) = default; |
| 162 | 119 |
| 163 uintptr_t is_valid() const { return flag_->IsValid(); } | 120 bool is_valid() const; |
| 164 | 121 |
| 165 private: | 122 private: |
| 166 // Note: To avoid null-checks, flag_ always points to either Flag::NullFlag() | |
| 167 // or some other object. | |
| 168 scoped_refptr<const Flag> flag_; | 123 scoped_refptr<const Flag> flag_; |
| 169 }; | 124 }; |
| 170 | 125 |
| 171 class BASE_EXPORT WeakReferenceOwner { | 126 class BASE_EXPORT WeakReferenceOwner { |
| 172 public: | 127 public: |
| 173 WeakReferenceOwner(); | 128 WeakReferenceOwner(); |
| 174 ~WeakReferenceOwner(); | 129 ~WeakReferenceOwner(); |
| 175 | 130 |
| 176 WeakReference GetRef() const; | 131 WeakReference GetRef() const; |
| 177 | 132 |
| 178 bool HasRefs() const { | 133 bool HasRefs() const { |
| 179 return flag_ != WeakReference::Flag::NullFlag() && !flag_->HasOneRef(); | 134 return flag_.get() && !flag_->HasOneRef(); |
| 180 } | 135 } |
| 181 | 136 |
| 182 void Invalidate(); | 137 void Invalidate(); |
| 183 | 138 |
| 184 private: | 139 private: |
| 185 mutable scoped_refptr<WeakReference::Flag> flag_; | 140 mutable scoped_refptr<WeakReference::Flag> flag_; |
| 186 }; | 141 }; |
| 187 | 142 |
| 188 // This class simplifies the implementation of WeakPtr's type conversion | 143 // This class simplifies the implementation of WeakPtr's type conversion |
| 189 // constructor by avoiding the need for a public accessor for ref_. A | 144 // constructor by avoiding the need for a public accessor for ref_. A |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 274 } | 229 } |
| 275 template <typename U> | 230 template <typename U> |
| 276 WeakPtr(WeakPtr<U>&& other) : WeakPtrBase(std::move(other)) { | 231 WeakPtr(WeakPtr<U>&& other) : WeakPtrBase(std::move(other)) { |
| 277 // Need to cast from U* to T* to do pointer adjustment in case of multiple | 232 // Need to cast from U* to T* to do pointer adjustment in case of multiple |
| 278 // inheritance. This also enforces the "U is a T" rule. | 233 // inheritance. This also enforces the "U is a T" rule. |
| 279 T* t = reinterpret_cast<U*>(other.ptr_); | 234 T* t = reinterpret_cast<U*>(other.ptr_); |
| 280 ptr_ = reinterpret_cast<uintptr_t>(t); | 235 ptr_ = reinterpret_cast<uintptr_t>(t); |
| 281 } | 236 } |
| 282 | 237 |
| 283 T* get() const { | 238 T* get() const { |
| 284 // Intentionally bitwise and; see command on Flag::IsValid(). This provides | 239 return ref_.is_valid() ? reinterpret_cast<T*>(ptr_) : nullptr; |
| 285 // a fast way of conditionally retrieving the pointer, and conveniently sets | |
| 286 // EFLAGS for any null-check performed by the caller. | |
| 287 return reinterpret_cast<T*>(ref_.is_valid() & ptr_); | |
| 288 } | 240 } |
| 289 | 241 |
| 290 T& operator*() const { | 242 T& operator*() const { |
| 291 DCHECK(get() != nullptr); | 243 DCHECK(get() != nullptr); |
| 292 return *get(); | 244 return *get(); |
| 293 } | 245 } |
| 294 T* operator->() const { | 246 T* operator->() const { |
| 295 DCHECK(get() != nullptr); | 247 DCHECK(get() != nullptr); |
| 296 return get(); | 248 return get(); |
| 297 } | 249 } |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 418 // base::WeakPtr<Derived> ptr = derived.AsWeakPtr(); // Fails. | 370 // base::WeakPtr<Derived> ptr = derived.AsWeakPtr(); // Fails. |
| 419 | 371 |
| 420 template <typename Derived> | 372 template <typename Derived> |
| 421 WeakPtr<Derived> AsWeakPtr(Derived* t) { | 373 WeakPtr<Derived> AsWeakPtr(Derived* t) { |
| 422 return internal::SupportsWeakPtrBase::StaticAsWeakPtr<Derived>(t); | 374 return internal::SupportsWeakPtrBase::StaticAsWeakPtr<Derived>(t); |
| 423 } | 375 } |
| 424 | 376 |
| 425 } // namespace base | 377 } // namespace base |
| 426 | 378 |
| 427 #endif // BASE_MEMORY_WEAK_PTR_H_ | 379 #endif // BASE_MEMORY_WEAK_PTR_H_ |
| OLD | NEW |