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 |