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

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

Issue 1602443003: Improve GetWeakPtr() to better protect against unsafe usage patterns. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase Created 3 years, 9 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') | no next file with comments »
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 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 void Invalidate();
100 bool IsValid() const; 100 bool IsValid() const;
101 101
102 void DetachFromSequence();
103
102 private: 104 private:
103 friend class base::RefCountedThreadSafe<Flag>; 105 friend class base::RefCountedThreadSafe<Flag>;
104 106
105 ~Flag(); 107 ~Flag();
106 108
107 SequenceChecker sequence_checker_; 109 SequenceChecker sequence_checker_;
108 bool is_valid_; 110 bool is_valid_;
109 }; 111 };
110 112
111 WeakReference(); 113 WeakReference();
112 explicit WeakReference(const Flag* flag); 114 explicit WeakReference(const scoped_refptr<Flag>& flag);
113 ~WeakReference(); 115 ~WeakReference();
114 116
115 WeakReference(WeakReference&& other); 117 WeakReference(WeakReference&& other);
116 WeakReference(const WeakReference& other); 118 WeakReference(const WeakReference& other);
117 WeakReference& operator=(WeakReference&& other) = default; 119 WeakReference& operator=(WeakReference&& other) = default;
118 WeakReference& operator=(const WeakReference& other) = default; 120 WeakReference& operator=(const WeakReference& other) = default;
119 121
120 bool is_valid() const; 122 bool is_valid() const;
121 123
122 private: 124 private:
123 scoped_refptr<const Flag> flag_; 125 scoped_refptr<const Flag> flag_;
124 }; 126 };
125 127
126 class BASE_EXPORT WeakReferenceOwner { 128 class BASE_EXPORT WeakReferenceOwner {
127 public: 129 public:
128 WeakReferenceOwner(); 130 WeakReferenceOwner();
129 ~WeakReferenceOwner(); 131 ~WeakReferenceOwner();
130 132
131 WeakReference GetRef() const; 133 WeakReference GetRef() const;
132 134
133 bool HasRefs() const { 135 bool HasRefs() const { return flag_ && !flag_->HasOneRef(); }
134 return flag_.get() && !flag_->HasOneRef();
135 }
136 136
137 void Invalidate(); 137 void Invalidate();
138 138
139 void DetachFromSequence();
140
139 private: 141 private:
140 mutable scoped_refptr<WeakReference::Flag> flag_; 142 mutable scoped_refptr<WeakReference::Flag> flag_;
141 }; 143 };
142 144
143 // This class simplifies the implementation of WeakPtr's type conversion 145 // This class simplifies the implementation of WeakPtr's type conversion
144 // constructor by avoiding the need for a public accessor for ref_. A 146 // constructor by avoiding the need for a public accessor for ref_. A
145 // WeakPtr<T> cannot access the private members of WeakPtr<U>, so this 147 // WeakPtr<T> cannot access the private members of WeakPtr<U>, so this
146 // base class gives us a way to access ref_ in a protected fashion. 148 // base class gives us a way to access ref_ in a protected fashion.
147 class BASE_EXPORT WeakPtrBase { 149 class BASE_EXPORT WeakPtrBase {
148 public: 150 public:
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
281 // useful when working with primitive types. For example, you could have a 283 // useful when working with primitive types. For example, you could have a
282 // WeakPtrFactory<bool> that is used to pass around a weak reference to a bool. 284 // WeakPtrFactory<bool> that is used to pass around a weak reference to a bool.
283 template <class T> 285 template <class T>
284 class WeakPtrFactory { 286 class WeakPtrFactory {
285 public: 287 public:
286 explicit WeakPtrFactory(T* ptr) : ptr_(ptr) { 288 explicit WeakPtrFactory(T* ptr) : ptr_(ptr) {
287 } 289 }
288 290
289 ~WeakPtrFactory() { ptr_ = nullptr; } 291 ~WeakPtrFactory() { ptr_ = nullptr; }
290 292
293 // Returns a new WeakPtr. Although GetWeakPtr() can be called from any thread
294 // (assuming calling code ensures the WeakPtrFactory is still live at the
295 // time), it is not safe to call concurrently from separate threads. Code
296 // which hands-off WeakPtrs to separate threads for them to Bind() into
297 // posted tasks, for example, should usually take a WeakPtr during setup
298 // and store it for later use, rather than call GetWeakPtr() at Bind() time.
291 WeakPtr<T> GetWeakPtr() { 299 WeakPtr<T> GetWeakPtr() {
292 DCHECK(ptr_); 300 DCHECK(ptr_);
293 return WeakPtr<T>(weak_reference_owner_.GetRef(), ptr_); 301 return WeakPtr<T>(weak_reference_owner_.GetRef(), ptr_);
294 } 302 }
295 303
296 // Call this method to invalidate all existing weak pointers. 304 // Invalidates all existing weak pointers issued by this factory.
297 void InvalidateWeakPtrs() { 305 void InvalidateWeakPtrs() {
298 DCHECK(ptr_); 306 DCHECK(ptr_);
299 weak_reference_owner_.Invalidate(); 307 weak_reference_owner_.Invalidate();
300 } 308 }
301 309
302 // Call this method to determine if any weak pointers exist. 310 // Returns true if one or more WeakPtrs issued by this factory still exist.
303 bool HasWeakPtrs() const { 311 bool HasWeakPtrs() const {
304 DCHECK(ptr_); 312 DCHECK(ptr_);
305 return weak_reference_owner_.HasRefs(); 313 return weak_reference_owner_.HasRefs();
306 } 314 }
307 315
308 private: 316 private:
309 internal::WeakReferenceOwner weak_reference_owner_; 317 internal::WeakReferenceOwner weak_reference_owner_;
310 T* ptr_; 318 T* ptr_;
311 DISALLOW_IMPLICIT_CONSTRUCTORS(WeakPtrFactory); 319 DISALLOW_IMPLICIT_CONSTRUCTORS(WeakPtrFactory);
312 }; 320 };
313 321
314 // A class may extend from SupportsWeakPtr to let others take weak pointers to 322 // A class may extend from SupportsWeakPtr to let others take weak pointers to
315 // it. This avoids the class itself implementing boilerplate to dispense weak 323 // it. This avoids the class itself implementing boilerplate to dispense weak
316 // pointers. However, since SupportsWeakPtr's destructor won't invalidate 324 // pointers. However, since SupportsWeakPtr's destructor won't invalidate
317 // weak pointers to the class until after the derived class' members have been 325 // weak pointers to the class until after the derived class' members have been
318 // destroyed, its use can lead to subtle use-after-destroy issues. 326 // destroyed, its use can lead to subtle use-after-destroy issues.
319 template <class T> 327 template <class T>
320 class SupportsWeakPtr : public internal::SupportsWeakPtrBase { 328 class SupportsWeakPtr : public internal::SupportsWeakPtrBase {
321 public: 329 public:
322 SupportsWeakPtr() {} 330 SupportsWeakPtr() {}
323 331
324 WeakPtr<T> AsWeakPtr() { 332 WeakPtr<T> AsWeakPtr() {
325 return WeakPtr<T>(weak_reference_owner_.GetRef(), static_cast<T*>(this)); 333 return WeakPtr<T>(weak_reference_owner_.GetRef(), static_cast<T*>(this));
326 } 334 }
327 335
328 protected: 336 protected:
329 ~SupportsWeakPtr() {} 337 ~SupportsWeakPtr() {}
330 338
339 // Asserts that no issued WeakPtrs exist, and detaches the sequence binding.
340 void DetachFromSequence() { weak_reference_owner_.DetachFromSequence(); }
341
342 bool HasWeakPtrs() const { return weak_reference_owner_.HasRefs(); }
343
331 private: 344 private:
332 internal::WeakReferenceOwner weak_reference_owner_; 345 internal::WeakReferenceOwner weak_reference_owner_;
333 DISALLOW_COPY_AND_ASSIGN(SupportsWeakPtr); 346 DISALLOW_COPY_AND_ASSIGN(SupportsWeakPtr);
334 }; 347 };
335 348
336 // Helper function that uses type deduction to safely return a WeakPtr<Derived> 349 // Helper function that uses type deduction to safely return a WeakPtr<Derived>
337 // when Derived doesn't directly extend SupportsWeakPtr<Derived>, instead it 350 // when Derived doesn't directly extend SupportsWeakPtr<Derived>, instead it
338 // extends a Base that extends SupportsWeakPtr<Base>. 351 // extends a Base that extends SupportsWeakPtr<Base>.
339 // 352 //
340 // EXAMPLE: 353 // EXAMPLE:
(...skipping 11 matching lines...) Expand all
352 // base::WeakPtr<Derived> ptr = derived.AsWeakPtr(); // Fails. 365 // base::WeakPtr<Derived> ptr = derived.AsWeakPtr(); // Fails.
353 366
354 template <typename Derived> 367 template <typename Derived>
355 WeakPtr<Derived> AsWeakPtr(Derived* t) { 368 WeakPtr<Derived> AsWeakPtr(Derived* t) {
356 return internal::SupportsWeakPtrBase::StaticAsWeakPtr<Derived>(t); 369 return internal::SupportsWeakPtrBase::StaticAsWeakPtr<Derived>(t);
357 } 370 }
358 371
359 } // namespace base 372 } // namespace base
360 373
361 #endif // BASE_MEMORY_WEAK_PTR_H_ 374 #endif // BASE_MEMORY_WEAK_PTR_H_
OLDNEW
« no previous file with comments | « no previous file | base/memory/weak_ptr.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698