Chromium Code Reviews| 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 void Invalidate(); | 99 // Get a pointer to the "Null Flag", a sentinel object used by WeakReference |
| 100 bool IsValid() const; | 100 // objects that don't point to a valid Flag, either because they're default |
| 101 // consturcted or because they have been invalidated. This can be used like | |
|
Nico
2017/06/28 20:57:03
typo consturcted
hans
2017/06/28 21:16:59
Done.
| |
| 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 } | |
| 101 | 137 |
| 102 private: | 138 private: |
| 103 friend class base::RefCountedThreadSafe<Flag>; | 139 friend class base::RefCountedThreadSafe<Flag>; |
| 104 | 140 |
| 141 enum NullFlagTag { kNullFlagTag }; | |
| 142 Flag(NullFlagTag); | |
| 143 | |
| 105 ~Flag(); | 144 ~Flag(); |
| 106 | 145 |
| 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. | |
| 107 SequenceChecker sequence_checker_; | 150 SequenceChecker sequence_checker_; |
| 108 bool is_valid_; | 151 #endif |
| 109 }; | 152 }; |
| 110 | 153 |
| 111 WeakReference(); | 154 WeakReference(); |
| 112 explicit WeakReference(const Flag* flag); | 155 explicit WeakReference(const Flag* flag); |
| 113 ~WeakReference(); | 156 ~WeakReference(); |
| 114 | 157 |
| 115 WeakReference(WeakReference&& other); | 158 WeakReference(WeakReference&& other); |
| 116 WeakReference(const WeakReference& other); | 159 WeakReference(const WeakReference& other); |
| 117 WeakReference& operator=(WeakReference&& other) = default; | 160 WeakReference& operator=(WeakReference&& other) = default; |
| 118 WeakReference& operator=(const WeakReference& other) = default; | 161 WeakReference& operator=(const WeakReference& other) = default; |
| 119 | 162 |
| 120 bool is_valid() const; | 163 uintptr_t is_valid() const { return flag_->IsValid(); } |
| 121 | 164 |
| 122 private: | 165 private: |
| 166 // Note: To avoid null-checks, flag_ always points to either Flag::NullFlag() | |
| 167 // or some other object. | |
| 123 scoped_refptr<const Flag> flag_; | 168 scoped_refptr<const Flag> flag_; |
| 124 }; | 169 }; |
| 125 | 170 |
| 126 class BASE_EXPORT WeakReferenceOwner { | 171 class BASE_EXPORT WeakReferenceOwner { |
| 127 public: | 172 public: |
| 128 WeakReferenceOwner(); | 173 WeakReferenceOwner(); |
| 129 ~WeakReferenceOwner(); | 174 ~WeakReferenceOwner(); |
| 130 | 175 |
| 131 WeakReference GetRef() const; | 176 WeakReference GetRef() const; |
| 132 | 177 |
| 133 bool HasRefs() const { | 178 bool HasRefs() const { |
| 134 return flag_.get() && !flag_->HasOneRef(); | 179 return flag_ != WeakReference::Flag::NullFlag() && !flag_->HasOneRef(); |
| 135 } | 180 } |
| 136 | 181 |
| 137 void Invalidate(); | 182 void Invalidate(); |
| 138 | 183 |
| 139 private: | 184 private: |
| 140 mutable scoped_refptr<WeakReference::Flag> flag_; | 185 mutable scoped_refptr<WeakReference::Flag> flag_; |
| 141 }; | 186 }; |
| 142 | 187 |
| 143 // This class simplifies the implementation of WeakPtr's type conversion | 188 // This class simplifies the implementation of WeakPtr's type conversion |
| 144 // constructor by avoiding the need for a public accessor for ref_. A | 189 // constructor by avoiding the need for a public accessor for ref_. A |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 215 | 260 |
| 216 // Allow conversion from U to T provided U "is a" T. Note that this | 261 // Allow conversion from U to T provided U "is a" T. Note that this |
| 217 // is separate from the (implicit) copy and move constructors. | 262 // is separate from the (implicit) copy and move constructors. |
| 218 template <typename U> | 263 template <typename U> |
| 219 WeakPtr(const WeakPtr<U>& other) : WeakPtrBase(other), ptr_(other.ptr_) { | 264 WeakPtr(const WeakPtr<U>& other) : WeakPtrBase(other), ptr_(other.ptr_) { |
| 220 } | 265 } |
| 221 template <typename U> | 266 template <typename U> |
| 222 WeakPtr(WeakPtr<U>&& other) | 267 WeakPtr(WeakPtr<U>&& other) |
| 223 : WeakPtrBase(std::move(other)), ptr_(other.ptr_) {} | 268 : WeakPtrBase(std::move(other)), ptr_(other.ptr_) {} |
| 224 | 269 |
| 225 T* get() const { return ref_.is_valid() ? ptr_ : nullptr; } | 270 T* get() const { |
| 271 // Intentionally bitwise and; see command on Flag::IsValid(). This provides | |
| 272 // a fast way of conditionally retrieving the pointer, and conveniently sets | |
| 273 // EFLAGS for any null-check performed by the caller. | |
| 274 return reinterpret_cast<T*>(ref_.is_valid() & | |
| 275 reinterpret_cast<uintptr_t>(ptr_)); | |
| 276 } | |
| 226 | 277 |
| 227 T& operator*() const { | 278 T& operator*() const { |
| 228 DCHECK(get() != nullptr); | 279 DCHECK(get() != nullptr); |
| 229 return *get(); | 280 return *get(); |
| 230 } | 281 } |
| 231 T* operator->() const { | 282 T* operator->() const { |
| 232 DCHECK(get() != nullptr); | 283 DCHECK(get() != nullptr); |
| 233 return get(); | 284 return get(); |
| 234 } | 285 } |
| 235 | 286 |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 352 // base::WeakPtr<Derived> ptr = derived.AsWeakPtr(); // Fails. | 403 // base::WeakPtr<Derived> ptr = derived.AsWeakPtr(); // Fails. |
| 353 | 404 |
| 354 template <typename Derived> | 405 template <typename Derived> |
| 355 WeakPtr<Derived> AsWeakPtr(Derived* t) { | 406 WeakPtr<Derived> AsWeakPtr(Derived* t) { |
| 356 return internal::SupportsWeakPtrBase::StaticAsWeakPtr<Derived>(t); | 407 return internal::SupportsWeakPtrBase::StaticAsWeakPtr<Derived>(t); |
| 357 } | 408 } |
| 358 | 409 |
| 359 } // namespace base | 410 } // namespace base |
| 360 | 411 |
| 361 #endif // BASE_MEMORY_WEAK_PTR_H_ | 412 #endif // BASE_MEMORY_WEAK_PTR_H_ |
| OLD | NEW |