weak_ptr.h (17222B)
1 // Copyright 2012 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 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 7 // owner, at any time, most commonly when the object is about to be deleted. 8 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 11 // object vanishing and e.g. tasks posted to it being silently dropped. 12 // Reference-counting such an object would complicate the ownership graph and 13 // make it harder to reason about the object's lifetime. 14 15 // EXAMPLE: 16 // 17 // class Controller { 18 // public: 19 // void SpawnWorker() { Worker::StartNew(weak_factory_.GetWeakPtr()); } 20 // void WorkComplete(const Result& result) { ... } 21 // private: 22 // // Member variables should appear before the WeakPtrFactory, to ensure 23 // // that any WeakPtrs to Controller are invalidated before its members 24 // // variable's destructors are executed, rendering them invalid. 25 // WeakPtrFactory<Controller> weak_factory_{this}; 26 // }; 27 // 28 // class Worker { 29 // public: 30 // static void StartNew(WeakPtr<Controller> controller) { 31 // // Move WeakPtr when possible to avoid atomic refcounting churn on its 32 // // internal state. 33 // Worker* worker = new Worker(std::move(controller)); 34 // // Kick off asynchronous processing... 35 // } 36 // private: 37 // Worker(WeakPtr<Controller> controller) 38 // : controller_(std::move(controller)) {} 39 // void DidCompleteAsynchronousProcessing(const Result& result) { 40 // if (controller_) 41 // controller_->WorkComplete(result); 42 // } 43 // WeakPtr<Controller> controller_; 44 // }; 45 // 46 // With this implementation a caller may use SpawnWorker() to dispatch multiple 47 // Workers and subsequently delete the Controller, without waiting for all 48 // Workers to have completed. 49 50 // ------------------------- IMPORTANT: Thread-safety ------------------------- 51 52 // Weak pointers may be passed safely between sequences, but must always be 53 // dereferenced and invalidated on the same SequencedTaskRunner otherwise 54 // checking the pointer would be racey. 55 // 56 // To ensure correct use, the first time a WeakPtr issued by a WeakPtrFactory 57 // is dereferenced, the factory and its WeakPtrs become bound to the calling 58 // sequence or current SequencedWorkerPool token, and cannot be dereferenced or 59 // invalidated on any other task runner. Bound WeakPtrs can still be handed 60 // off to other task runners, e.g. to use to post tasks back to object on the 61 // bound sequence. 62 // 63 // If all WeakPtr objects are destroyed or invalidated then the factory is 64 // unbound from the SequencedTaskRunner/Thread. The WeakPtrFactory may then be 65 // destroyed, or new WeakPtr objects may be used, from a different sequence. 66 // 67 // Thus, at least one WeakPtr object must exist and have been dereferenced on 68 // the correct sequence to enforce that other WeakPtr objects will enforce they 69 // are used on the desired sequence. 70 71 #ifndef BASE_MEMORY_WEAK_PTR_H_ 72 #define BASE_MEMORY_WEAK_PTR_H_ 73 74 #include <cstddef> 75 #include <type_traits> 76 #include <utility> 77 78 #include "base/base_export.h" 79 #include "base/check.h" 80 #include "base/compiler_specific.h" 81 #include "base/dcheck_is_on.h" 82 #include "base/memory/raw_ptr.h" 83 #include "base/memory/ref_counted.h" 84 #include "base/memory/safe_ref_traits.h" 85 #include "base/sequence_checker.h" 86 #include "base/synchronization/atomic_flag.h" 87 #include "base/types/pass_key.h" 88 89 namespace base { 90 91 namespace sequence_manager::internal { 92 class TaskQueueImpl; 93 } 94 95 template <typename T> class SupportsWeakPtr; 96 template <typename T> class WeakPtr; 97 98 namespace internal { 99 // These classes are part of the WeakPtr implementation. 100 // DO NOT USE THESE CLASSES DIRECTLY YOURSELF. 101 102 class BASE_EXPORT TRIVIAL_ABI WeakReference { 103 public: 104 // Although Flag is bound to a specific SequencedTaskRunner, it may be 105 // deleted from another via base::WeakPtr::~WeakPtr(). 106 class BASE_EXPORT Flag : public RefCountedThreadSafe<Flag> { 107 public: 108 Flag(); 109 110 void Invalidate(); 111 bool IsValid() const; 112 113 bool MaybeValid() const; 114 115 #if DCHECK_IS_ON() 116 void DetachFromSequence(); 117 void BindToCurrentSequence(); 118 #endif 119 120 private: 121 friend class base::RefCountedThreadSafe<Flag>; 122 123 ~Flag(); 124 125 SEQUENCE_CHECKER(sequence_checker_); 126 AtomicFlag invalidated_; 127 }; 128 129 WeakReference(); 130 explicit WeakReference(const scoped_refptr<Flag>& flag); 131 ~WeakReference(); 132 133 WeakReference(const WeakReference& other); 134 WeakReference& operator=(const WeakReference& other); 135 136 WeakReference(WeakReference&& other) noexcept; 137 WeakReference& operator=(WeakReference&& other) noexcept; 138 139 void Reset(); 140 // Returns whether the WeakReference is valid, meaning the WeakPtrFactory has 141 // not invalidated the pointer. Unlike, RefIsMaybeValid(), this may only be 142 // called from the same sequence as where the WeakPtr was created. 143 bool IsValid() const; 144 // Returns false if the WeakReference is confirmed to be invalid. This call is 145 // safe to make from any thread, e.g. to optimize away unnecessary work, but 146 // RefIsValid() must always be called, on the correct sequence, before 147 // actually using the pointer. 148 // 149 // Warning: as with any object, this call is only thread-safe if the WeakPtr 150 // instance isn't being re-assigned or reset() racily with this call. 151 bool MaybeValid() const; 152 153 private: 154 scoped_refptr<const Flag> flag_; 155 }; 156 157 class BASE_EXPORT WeakReferenceOwner { 158 public: 159 WeakReferenceOwner(); 160 ~WeakReferenceOwner(); 161 162 WeakReference GetRef() const; 163 164 bool HasRefs() const { return !flag_->HasOneRef(); } 165 166 void Invalidate(); 167 void BindToCurrentSequence(); 168 169 private: 170 scoped_refptr<WeakReference::Flag> flag_; 171 }; 172 173 // This class provides a common implementation of common functions that would 174 // otherwise get instantiated separately for each distinct instantiation of 175 // SupportsWeakPtr<>. 176 class SupportsWeakPtrBase { 177 public: 178 // A safe static downcast of a WeakPtr<Base> to WeakPtr<Derived>. This 179 // conversion will only compile if Derived singly inherits from 180 // SupportsWeakPtr<Base>. See base::AsWeakPtr() below for a helper function 181 // that makes calling this easier. 182 // 183 // Precondition: t != nullptr 184 template<typename Derived> 185 static WeakPtr<Derived> StaticAsWeakPtr(Derived* t) { 186 static_assert(std::is_base_of_v<internal::SupportsWeakPtrBase, Derived>, 187 "AsWeakPtr argument must inherit from SupportsWeakPtr"); 188 using Base = typename decltype(ExtractSinglyInheritedBase(t))::Base; 189 // Ensure SupportsWeakPtr<Base>::AsWeakPtr() is called even if the subclass 190 // hides or overloads it. 191 WeakPtr<Base> weak = static_cast<SupportsWeakPtr<Base>*>(t)->AsWeakPtr(); 192 return WeakPtr<Derived>(weak.CloneWeakReference(), 193 static_cast<Derived*>(weak.ptr_)); 194 } 195 196 private: 197 // This class can only be instantiated if the constructor argument inherits 198 // from SupportsWeakPtr<T> in exactly one way. 199 template <typename T> 200 struct ExtractSinglyInheritedBase; 201 template <typename T> 202 struct ExtractSinglyInheritedBase<SupportsWeakPtr<T>> { 203 using Base = T; 204 explicit ExtractSinglyInheritedBase(SupportsWeakPtr<T>*); 205 }; 206 #if !defined(MOZ_SANDBOX) 207 template <typename T> 208 ExtractSinglyInheritedBase(SupportsWeakPtr<T>*) 209 -> ExtractSinglyInheritedBase<SupportsWeakPtr<T>>; 210 #endif 211 }; 212 213 // Forward declaration from safe_ptr.h. 214 template <typename T> 215 SafeRef<T> MakeSafeRefFromWeakPtrInternals(internal::WeakReference&& ref, 216 T* ptr); 217 218 } // namespace internal 219 220 template <typename T> class WeakPtrFactory; 221 222 // The WeakPtr class holds a weak reference to |T*|. 223 // 224 // This class is designed to be used like a normal pointer. You should always 225 // null-test an object of this class before using it or invoking a method that 226 // may result in the underlying object being destroyed. 227 // 228 // EXAMPLE: 229 // 230 // class Foo { ... }; 231 // WeakPtr<Foo> foo; 232 // if (foo) 233 // foo->method(); 234 // 235 template <typename T> 236 class TRIVIAL_ABI WeakPtr { 237 public: 238 WeakPtr() = default; 239 // NOLINTNEXTLINE(google-explicit-constructor) 240 WeakPtr(std::nullptr_t) {} 241 242 // Allow conversion from U to T provided U "is a" T. Note that this 243 // is separate from the (implicit) copy and move constructors. 244 template <typename U, 245 typename = std::enable_if_t<std::is_convertible_v<U*, T*>>> 246 // NOLINTNEXTLINE(google-explicit-constructor) 247 WeakPtr(const WeakPtr<U>& other) : ref_(other.ref_), ptr_(other.ptr_) {} 248 template <typename U, 249 typename = std::enable_if_t<std::is_convertible_v<U*, T*>>> 250 // NOLINTNEXTLINE(google-explicit-constructor) 251 WeakPtr& operator=(const WeakPtr<U>& other) { 252 ref_ = other.ref_; 253 ptr_ = other.ptr_; 254 return *this; 255 } 256 257 template <typename U, 258 typename = std::enable_if_t<std::is_convertible_v<U*, T*>>> 259 // NOLINTNEXTLINE(google-explicit-constructor) 260 WeakPtr(WeakPtr<U>&& other) 261 : ref_(std::move(other.ref_)), ptr_(std::move(other.ptr_)) {} 262 template <typename U, 263 typename = std::enable_if_t<std::is_convertible_v<U*, T*>>> 264 // NOLINTNEXTLINE(google-explicit-constructor) 265 WeakPtr& operator=(WeakPtr<U>&& other) { 266 ref_ = std::move(other.ref_); 267 ptr_ = std::move(other.ptr_); 268 return *this; 269 } 270 271 T* get() const { return ref_.IsValid() ? ptr_ : nullptr; } 272 273 // Provide access to the underlying T as a reference. Will CHECK() if the T 274 // pointee is no longer alive. 275 T& operator*() const { 276 CHECK(ref_.IsValid()); 277 return *ptr_; 278 } 279 280 // Used to call methods on the underlying T. Will CHECK() if the T pointee is 281 // no longer alive. 282 T* operator->() const { 283 CHECK(ref_.IsValid()); 284 return ptr_; 285 } 286 287 // Allow conditionals to test validity, e.g. if (weak_ptr) {...}; 288 explicit operator bool() const { return get() != nullptr; } 289 290 // Resets the WeakPtr to hold nothing. 291 // 292 // The `get()` method will return `nullptr` thereafter, and `MaybeValid()` 293 // will be `false`. 294 void reset() { 295 ref_.Reset(); 296 ptr_ = nullptr; 297 } 298 299 // Returns false if the WeakPtr is confirmed to be invalid. This call is safe 300 // to make from any thread, e.g. to optimize away unnecessary work, but 301 // RefIsValid() must always be called, on the correct sequence, before 302 // actually using the pointer. 303 // 304 // Warning: as with any object, this call is only thread-safe if the WeakPtr 305 // instance isn't being re-assigned or reset() racily with this call. 306 bool MaybeValid() const { return ref_.MaybeValid(); } 307 308 // Returns whether the object |this| points to has been invalidated. This can 309 // be used to distinguish a WeakPtr to a destroyed object from one that has 310 // been explicitly set to null. 311 bool WasInvalidated() const { return ptr_ && !ref_.IsValid(); } 312 313 private: 314 friend class internal::SupportsWeakPtrBase; 315 template <typename U> friend class WeakPtr; 316 friend class SupportsWeakPtr<T>; 317 friend class WeakPtrFactory<T>; 318 friend class WeakPtrFactory<std::remove_const_t<T>>; 319 320 WeakPtr(internal::WeakReference&& ref, T* ptr) 321 : ref_(std::move(ref)), ptr_(ptr) { 322 DCHECK(ptr); 323 } 324 325 internal::WeakReference CloneWeakReference() const { return ref_; } 326 327 internal::WeakReference ref_; 328 329 // This pointer is only valid when ref_.is_valid() is true. Otherwise, its 330 // value is undefined (as opposed to nullptr). The pointer is allowed to 331 // dangle as we verify its liveness through `ref_` before allowing access to 332 // the pointee. We don't use raw_ptr<T> here to prevent WeakPtr from keeping 333 // the memory allocation in quarantine, as it can't be accessed through the 334 // WeakPtr. 335 RAW_PTR_EXCLUSION T* ptr_ = nullptr; 336 }; 337 338 // Allow callers to compare WeakPtrs against nullptr to test validity. 339 template <class T> 340 bool operator!=(const WeakPtr<T>& weak_ptr, std::nullptr_t) { 341 return !(weak_ptr == nullptr); 342 } 343 template <class T> 344 bool operator!=(std::nullptr_t, const WeakPtr<T>& weak_ptr) { 345 return weak_ptr != nullptr; 346 } 347 template <class T> 348 bool operator==(const WeakPtr<T>& weak_ptr, std::nullptr_t) { 349 return weak_ptr.get() == nullptr; 350 } 351 template <class T> 352 bool operator==(std::nullptr_t, const WeakPtr<T>& weak_ptr) { 353 return weak_ptr == nullptr; 354 } 355 356 namespace internal { 357 class BASE_EXPORT WeakPtrFactoryBase { 358 protected: 359 WeakPtrFactoryBase(uintptr_t ptr); 360 ~WeakPtrFactoryBase(); 361 internal::WeakReferenceOwner weak_reference_owner_; 362 uintptr_t ptr_; 363 }; 364 } // namespace internal 365 366 // A class may be composed of a WeakPtrFactory and thereby 367 // control how it exposes weak pointers to itself. This is helpful if you only 368 // need weak pointers within the implementation of a class. This class is also 369 // useful when working with primitive types. For example, you could have a 370 // WeakPtrFactory<bool> that is used to pass around a weak reference to a bool. 371 template <class T> 372 class WeakPtrFactory : public internal::WeakPtrFactoryBase { 373 public: 374 WeakPtrFactory() = delete; 375 376 explicit WeakPtrFactory(T* ptr) 377 : WeakPtrFactoryBase(reinterpret_cast<uintptr_t>(ptr)) {} 378 379 WeakPtrFactory(const WeakPtrFactory&) = delete; 380 WeakPtrFactory& operator=(const WeakPtrFactory&) = delete; 381 382 ~WeakPtrFactory() = default; 383 384 WeakPtr<const T> GetWeakPtr() const { 385 return WeakPtr<const T>(weak_reference_owner_.GetRef(), 386 reinterpret_cast<const T*>(ptr_)); 387 } 388 389 template <int&... ExplicitArgumentBarrier, 390 typename U = T, 391 typename = std::enable_if_t<!std::is_const_v<U>>> 392 WeakPtr<T> GetWeakPtr() { 393 return WeakPtr<T>(weak_reference_owner_.GetRef(), 394 reinterpret_cast<T*>(ptr_)); 395 } 396 397 template <int&... ExplicitArgumentBarrier, 398 typename U = T, 399 typename = std::enable_if_t<!std::is_const_v<U>>> 400 WeakPtr<T> GetMutableWeakPtr() const { 401 return WeakPtr<T>(weak_reference_owner_.GetRef(), 402 reinterpret_cast<T*>(ptr_)); 403 } 404 405 // Returns a smart pointer that is valid until the WeakPtrFactory is 406 // invalidated. Unlike WeakPtr, this smart pointer cannot be null, and cannot 407 // be checked to see if the WeakPtrFactory is invalidated. It's intended to 408 // express that the pointer will not (intentionally) outlive the `T` object it 409 // points to, and to crash safely in the case of a bug instead of causing a 410 // use-after-free. This type provides an alternative to WeakPtr to prevent 411 // use-after-free bugs without also introducing "fuzzy lifetimes" that can be 412 // checked for at runtime. 413 SafeRef<T> GetSafeRef() const { 414 return internal::MakeSafeRefFromWeakPtrInternals( 415 weak_reference_owner_.GetRef(), reinterpret_cast<T*>(ptr_)); 416 } 417 418 // Call this method to invalidate all existing weak pointers. 419 void InvalidateWeakPtrs() { 420 DCHECK(ptr_); 421 weak_reference_owner_.Invalidate(); 422 } 423 424 // Call this method to determine if any weak pointers exist. 425 bool HasWeakPtrs() const { 426 DCHECK(ptr_); 427 return weak_reference_owner_.HasRefs(); 428 } 429 430 // Rebind the factory to the current sequence. This allows creating a task 431 // queue and associated weak pointers on a different thread from the one they 432 // are used on. 433 void BindToCurrentSequence( 434 PassKey<sequence_manager::internal::TaskQueueImpl>) { 435 weak_reference_owner_.BindToCurrentSequence(); 436 } 437 }; 438 439 // A class may extend from SupportsWeakPtr to let others take weak pointers to 440 // it. This avoids the class itself implementing boilerplate to dispense weak 441 // pointers. However, since SupportsWeakPtr's destructor won't invalidate 442 // weak pointers to the class until after the derived class' members have been 443 // destroyed, its use can lead to subtle use-after-destroy issues. 444 template <class T> 445 class SupportsWeakPtr : public internal::SupportsWeakPtrBase { 446 public: 447 SupportsWeakPtr() = default; 448 449 SupportsWeakPtr(const SupportsWeakPtr&) = delete; 450 SupportsWeakPtr& operator=(const SupportsWeakPtr&) = delete; 451 452 WeakPtr<T> AsWeakPtr() { 453 return WeakPtr<T>(weak_reference_owner_.GetRef(), static_cast<T*>(this)); 454 } 455 456 protected: 457 ~SupportsWeakPtr() = default; 458 459 private: 460 internal::WeakReferenceOwner weak_reference_owner_; 461 }; 462 463 // Helper function that uses type deduction to safely return a WeakPtr<Derived> 464 // when Derived doesn't directly extend SupportsWeakPtr<Derived>, instead it 465 // extends a Base that extends SupportsWeakPtr<Base>. 466 // 467 // EXAMPLE: 468 // class Base : public base::SupportsWeakPtr<Producer> {}; 469 // class Derived : public Base {}; 470 // 471 // Derived derived; 472 // base::WeakPtr<Derived> ptr = base::AsWeakPtr(&derived); 473 // 474 // Note that the following doesn't work (invalid type conversion) since 475 // Derived::AsWeakPtr() is WeakPtr<Base> SupportsWeakPtr<Base>::AsWeakPtr(), 476 // and there's no way to safely cast WeakPtr<Base> to WeakPtr<Derived> at 477 // the caller. 478 // 479 // base::WeakPtr<Derived> ptr = derived.AsWeakPtr(); // Fails. 480 481 template <typename Derived> 482 WeakPtr<Derived> AsWeakPtr(Derived* t) { 483 return internal::SupportsWeakPtrBase::StaticAsWeakPtr<Derived>(t); 484 } 485 486 } // namespace base 487 488 #endif // BASE_MEMORY_WEAK_PTR_H_