Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(56)

Side by Side Diff: base/memory/weak_ptr.h

Issue 2963623002: Make base::WeakPtr::Get() fast (Closed)
Patch Set: Move WeakReference::Flag::Invalidate out-of-line; it's only called from WeakReferenceOwner::Invalid… Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | base/memory/weak_ptr.cc » ('j') | base/memory/weak_ptr.cc » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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_
OLDNEW
« no previous file with comments | « no previous file | base/memory/weak_ptr.cc » ('j') | base/memory/weak_ptr.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698