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 | |
100 // objects that don't point to a valid Flag, either because they're default | |
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 | |
99 void Invalidate(); | 106 void Invalidate(); |
100 bool IsValid() const; | 107 |
108 // Returns a pointer-sized bitmask of all 1s if valid or all 0s otherwise. | |
109 uintptr_t IsValid() const { | |
110 #if DCHECK_IS_ON() | |
111 if (this == NullFlag()) { | |
112 // The Null Flag does not participate in the sequence checks below. | |
113 // Since its state never changes, it can be accessed from any thread. | |
114 DCHECK(!is_valid_); | |
115 return 0; | |
116 } | |
117 DCHECK(sequence_checker_.CalledOnValidSequence()) | |
118 << "WeakPtrs must be checked on the same sequenced thread."; | |
119 #endif | |
120 return is_valid_; | |
121 } | |
101 | 122 |
102 private: | 123 private: |
103 friend class base::RefCountedThreadSafe<Flag>; | 124 friend class base::RefCountedThreadSafe<Flag>; |
104 | 125 |
126 enum NullFlagTag { kNullFlagTag }; | |
127 Flag(NullFlagTag); | |
128 | |
105 ~Flag(); | 129 ~Flag(); |
106 | 130 |
131 uintptr_t is_valid_; | |
132 #if DCHECK_IS_ON() | |
133 // Even if SequenceChecker is an empty class in non-dcheck builds, it still | |
134 // takes up space in the class. | |
107 SequenceChecker sequence_checker_; | 135 SequenceChecker sequence_checker_; |
gab
2017/07/18 20:31:08
You can use SEQUENCE_CHECKER() and friends macros
hans
2017/07/19 08:08:23
Done.
| |
108 bool is_valid_; | 136 #endif |
109 }; | 137 }; |
110 | 138 |
111 WeakReference(); | 139 WeakReference(); |
112 explicit WeakReference(const Flag* flag); | 140 explicit WeakReference(const Flag* flag); |
113 ~WeakReference(); | 141 ~WeakReference(); |
114 | 142 |
115 WeakReference(WeakReference&& other); | 143 WeakReference(WeakReference&& other); |
116 WeakReference(const WeakReference& other); | 144 WeakReference(const WeakReference& other); |
117 WeakReference& operator=(WeakReference&& other) = default; | 145 WeakReference& operator=(WeakReference&& other) = default; |
118 WeakReference& operator=(const WeakReference& other) = default; | 146 WeakReference& operator=(const WeakReference& other) = default; |
119 | 147 |
120 bool is_valid() const; | 148 uintptr_t is_valid() const { return flag_->IsValid(); } |
121 | 149 |
122 private: | 150 private: |
151 // Note: To avoid null-checks, flag_ always points to either Flag::NullFlag() | |
152 // or some other object. | |
123 scoped_refptr<const Flag> flag_; | 153 scoped_refptr<const Flag> flag_; |
124 }; | 154 }; |
125 | 155 |
126 class BASE_EXPORT WeakReferenceOwner { | 156 class BASE_EXPORT WeakReferenceOwner { |
127 public: | 157 public: |
128 WeakReferenceOwner(); | 158 WeakReferenceOwner(); |
129 ~WeakReferenceOwner(); | 159 ~WeakReferenceOwner(); |
130 | 160 |
131 WeakReference GetRef() const; | 161 WeakReference GetRef() const; |
132 | 162 |
133 bool HasRefs() const { | 163 bool HasRefs() const { |
134 return flag_.get() && !flag_->HasOneRef(); | 164 return flag_ != WeakReference::Flag::NullFlag() && !flag_->HasOneRef(); |
135 } | 165 } |
136 | 166 |
137 void Invalidate(); | 167 void Invalidate(); |
138 | 168 |
139 private: | 169 private: |
140 mutable scoped_refptr<WeakReference::Flag> flag_; | 170 mutable scoped_refptr<WeakReference::Flag> flag_; |
141 }; | 171 }; |
142 | 172 |
143 // This class simplifies the implementation of WeakPtr's type conversion | 173 // This class simplifies the implementation of WeakPtr's type conversion |
144 // constructor by avoiding the need for a public accessor for ref_. A | 174 // 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... | |
229 } | 259 } |
230 template <typename U> | 260 template <typename U> |
231 WeakPtr(WeakPtr<U>&& other) : WeakPtrBase(std::move(other)) { | 261 WeakPtr(WeakPtr<U>&& other) : WeakPtrBase(std::move(other)) { |
232 // Need to cast from U* to T* to do pointer adjustment in case of multiple | 262 // Need to cast from U* to T* to do pointer adjustment in case of multiple |
233 // inheritance. This also enforces the "U is a T" rule. | 263 // inheritance. This also enforces the "U is a T" rule. |
234 T* t = reinterpret_cast<U*>(other.ptr_); | 264 T* t = reinterpret_cast<U*>(other.ptr_); |
235 ptr_ = reinterpret_cast<uintptr_t>(t); | 265 ptr_ = reinterpret_cast<uintptr_t>(t); |
236 } | 266 } |
237 | 267 |
238 T* get() const { | 268 T* get() const { |
239 return ref_.is_valid() ? reinterpret_cast<T*>(ptr_) : nullptr; | 269 // Intentionally bitwise and; see command on Flag::IsValid(). This provides |
270 // a fast way of conditionally retrieving the pointer, and conveniently sets | |
271 // EFLAGS for any null-check performed by the caller. | |
272 return reinterpret_cast<T*>(ref_.is_valid() & ptr_); | |
240 } | 273 } |
241 | 274 |
242 T& operator*() const { | 275 T& operator*() const { |
243 DCHECK(get() != nullptr); | 276 DCHECK(get() != nullptr); |
244 return *get(); | 277 return *get(); |
245 } | 278 } |
246 T* operator->() const { | 279 T* operator->() const { |
247 DCHECK(get() != nullptr); | 280 DCHECK(get() != nullptr); |
248 return get(); | 281 return get(); |
249 } | 282 } |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
370 // base::WeakPtr<Derived> ptr = derived.AsWeakPtr(); // Fails. | 403 // base::WeakPtr<Derived> ptr = derived.AsWeakPtr(); // Fails. |
371 | 404 |
372 template <typename Derived> | 405 template <typename Derived> |
373 WeakPtr<Derived> AsWeakPtr(Derived* t) { | 406 WeakPtr<Derived> AsWeakPtr(Derived* t) { |
374 return internal::SupportsWeakPtrBase::StaticAsWeakPtr<Derived>(t); | 407 return internal::SupportsWeakPtrBase::StaticAsWeakPtr<Derived>(t); |
375 } | 408 } |
376 | 409 |
377 } // namespace base | 410 } // namespace base |
378 | 411 |
379 #endif // BASE_MEMORY_WEAK_PTR_H_ | 412 #endif // BASE_MEMORY_WEAK_PTR_H_ |
OLD | NEW |