• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
88 namespace performance_manager {
89 class FrameNodeImpl;
90 class PageNodeImpl;
91 class ProcessNodeImpl;
92 class WorkerNodeImpl;
93 }  // namespace performance_manager
94 
95 namespace base {
96 
97 namespace sequence_manager::internal {
98 class TaskQueueImpl;
99 }
100 
101 template <typename T> class WeakPtr;
102 
103 namespace internal {
104 // These classes are part of the WeakPtr implementation.
105 // DO NOT USE THESE CLASSES DIRECTLY YOURSELF.
106 
107 class BASE_EXPORT TRIVIAL_ABI WeakReference {
108  public:
109   // Although Flag is bound to a specific SequencedTaskRunner, it may be
110   // deleted from another via base::WeakPtr::~WeakPtr().
111   class BASE_EXPORT Flag : public RefCountedThreadSafe<Flag> {
112    public:
113     Flag();
114 
115     void Invalidate();
116     bool IsValid() const;
117 
118     bool MaybeValid() const;
119 
120 #if DCHECK_IS_ON()
121     void DetachFromSequence();
122     void BindToCurrentSequence();
123 #endif
124 
125    private:
126     friend class base::RefCountedThreadSafe<Flag>;
127 
128     ~Flag();
129 
130     SEQUENCE_CHECKER(sequence_checker_);
131     AtomicFlag invalidated_;
132   };
133 
134   WeakReference();
135   explicit WeakReference(const scoped_refptr<Flag>& flag);
136   ~WeakReference();
137 
138   WeakReference(const WeakReference& other);
139   WeakReference& operator=(const WeakReference& other);
140 
141   WeakReference(WeakReference&& other) noexcept;
142   WeakReference& operator=(WeakReference&& other) noexcept;
143 
144   void Reset();
145   // Returns whether the WeakReference is valid, meaning the WeakPtrFactory has
146   // not invalidated the pointer. Unlike, RefIsMaybeValid(), this may only be
147   // called from the same sequence as where the WeakPtr was created.
148   bool IsValid() const;
149   // Returns false if the WeakReference is confirmed to be invalid. This call is
150   // safe to make from any thread, e.g. to optimize away unnecessary work, but
151   // RefIsValid() must always be called, on the correct sequence, before
152   // actually using the pointer.
153   //
154   // Warning: as with any object, this call is only thread-safe if the WeakPtr
155   // instance isn't being re-assigned or reset() racily with this call.
156   bool MaybeValid() const;
157 
158  private:
159   scoped_refptr<const Flag> flag_;
160 };
161 
162 class BASE_EXPORT WeakReferenceOwner {
163  public:
164   WeakReferenceOwner();
165   ~WeakReferenceOwner();
166 
167   WeakReference GetRef() const;
168 
HasRefs()169   bool HasRefs() const { return !flag_->HasOneRef(); }
170 
171   void Invalidate();
172   void BindToCurrentSequence();
173 
174  private:
175   scoped_refptr<WeakReference::Flag> flag_;
176 };
177 
178 // Forward declaration from safe_ptr.h.
179 template <typename T>
180 SafeRef<T> MakeSafeRefFromWeakPtrInternals(internal::WeakReference&& ref,
181                                            T* ptr);
182 
183 }  // namespace internal
184 
185 template <typename T> class WeakPtrFactory;
186 
187 // The WeakPtr class holds a weak reference to |T*|.
188 //
189 // This class is designed to be used like a normal pointer.  You should always
190 // null-test an object of this class before using it or invoking a method that
191 // may result in the underlying object being destroyed.
192 //
193 // EXAMPLE:
194 //
195 //   class Foo { ... };
196 //   WeakPtr<Foo> foo;
197 //   if (foo)
198 //     foo->method();
199 //
200 template <typename T>
201 class TRIVIAL_ABI WeakPtr {
202  public:
203   WeakPtr() = default;
204   // NOLINTNEXTLINE(google-explicit-constructor)
WeakPtr(std::nullptr_t)205   WeakPtr(std::nullptr_t) {}
206 
207   // Allow conversion from U to T provided U "is a" T. Note that this
208   // is separate from the (implicit) copy and move constructors.
209   template <typename U>
requires(std::convertible_to<U *,T * >)210     requires(std::convertible_to<U*, T*>)
211   // NOLINTNEXTLINE(google-explicit-constructor)
212   WeakPtr(const WeakPtr<U>& other) : ref_(other.ref_), ptr_(other.ptr_) {}
213   template <typename U>
requires(std::convertible_to<U *,T * >)214     requires(std::convertible_to<U*, T*>)
215   // NOLINTNEXTLINE(google-explicit-constructor)
216   WeakPtr& operator=(const WeakPtr<U>& other) {
217     ref_ = other.ref_;
218     ptr_ = other.ptr_;
219     return *this;
220   }
221 
222   template <typename U>
requires(std::convertible_to<U *,T * >)223     requires(std::convertible_to<U*, T*>)
224   // NOLINTNEXTLINE(google-explicit-constructor)
225   WeakPtr(WeakPtr<U>&& other)
226       : ref_(std::move(other.ref_)), ptr_(std::move(other.ptr_)) {}
227   template <typename U>
requires(std::convertible_to<U *,T * >)228     requires(std::convertible_to<U*, T*>)
229   // NOLINTNEXTLINE(google-explicit-constructor)
230   WeakPtr& operator=(WeakPtr<U>&& other) {
231     ref_ = std::move(other.ref_);
232     ptr_ = std::move(other.ptr_);
233     return *this;
234   }
235 
get()236   T* get() const { return ref_.IsValid() ? ptr_ : nullptr; }
237 
238   // Provide access to the underlying T as a reference. Will CHECK() if the T
239   // pointee is no longer alive.
240   T& operator*() const {
241     CHECK(ref_.IsValid());
242     return *ptr_;
243   }
244 
245   // Used to call methods on the underlying T. Will CHECK() if the T pointee is
246   // no longer alive.
247   T* operator->() const {
248     CHECK(ref_.IsValid());
249     return ptr_;
250   }
251 
252   // Allow conditionals to test validity, e.g. if (weak_ptr) {...};
253   explicit operator bool() const { return get() != nullptr; }
254 
255   // Resets the WeakPtr to hold nothing.
256   //
257   // The `get()` method will return `nullptr` thereafter, and `MaybeValid()`
258   // will be `false`.
reset()259   void reset() {
260     ref_.Reset();
261     ptr_ = nullptr;
262   }
263 
264   // Do not use this method. Almost all callers should instead use operator
265   // bool().
266   //
267   // There are a few rare cases where the caller intentionally needs to check
268   // validity of a base::WeakPtr on a sequence different from the bound sequence
269   // as an unavoidable performance optimization. This is the only valid use-case
270   // for this method. See
271   // https://docs.google.com/document/d/1IGzq9Nx69GS_2iynGmPWo5sFAD2DcCyBY1zIvZwF7k8
272   // for details.
273   //
274   // Returns false if the WeakPtr is confirmed to be invalid. This call is safe
275   // to make from any thread, e.g. to optimize away unnecessary work, but
276   // RefIsValid() must always be called, on the correct sequence, before
277   // actually using the pointer.
278   //
279   // Warning: as with any object, this call is only thread-safe if the WeakPtr
280   // instance isn't being re-assigned or reset() racily with this call.
MaybeValid()281   bool MaybeValid() const { return ref_.MaybeValid(); }
282 
283   // Returns whether the object |this| points to has been invalidated. This can
284   // be used to distinguish a WeakPtr to a destroyed object from one that has
285   // been explicitly set to null.
WasInvalidated()286   bool WasInvalidated() const { return ptr_ && !ref_.IsValid(); }
287 
288  private:
289   template <typename U> friend class WeakPtr;
290   friend class WeakPtrFactory<T>;
291   friend class WeakPtrFactory<std::remove_const_t<T>>;
292 
WeakPtr(internal::WeakReference && ref,T * ptr)293   WeakPtr(internal::WeakReference&& ref, T* ptr)
294       : ref_(std::move(ref)), ptr_(ptr) {
295     DCHECK(ptr);
296   }
297 
CloneWeakReference()298   internal::WeakReference CloneWeakReference() const { return ref_; }
299 
300   internal::WeakReference ref_;
301 
302   // This pointer is only valid when ref_.is_valid() is true.  Otherwise, its
303   // value is undefined (as opposed to nullptr). The pointer is allowed to
304   // dangle as we verify its liveness through `ref_` before allowing access to
305   // the pointee. We don't use raw_ptr<T> here to prevent WeakPtr from keeping
306   // the memory allocation in quarantine, as it can't be accessed through the
307   // WeakPtr.
308   RAW_PTR_EXCLUSION T* ptr_ = nullptr;
309 };
310 
311 // Allow callers to compare WeakPtrs against nullptr to test validity.
312 template <class T>
313 bool operator!=(const WeakPtr<T>& weak_ptr, std::nullptr_t) {
314   return !(weak_ptr == nullptr);
315 }
316 template <class T>
317 bool operator!=(std::nullptr_t, const WeakPtr<T>& weak_ptr) {
318   return weak_ptr != nullptr;
319 }
320 template <class T>
321 bool operator==(const WeakPtr<T>& weak_ptr, std::nullptr_t) {
322   return weak_ptr.get() == nullptr;
323 }
324 template <class T>
325 bool operator==(std::nullptr_t, const WeakPtr<T>& weak_ptr) {
326   return weak_ptr == nullptr;
327 }
328 
329 namespace internal {
330 class BASE_EXPORT WeakPtrFactoryBase {
331  protected:
332   WeakPtrFactoryBase(uintptr_t ptr);
333   ~WeakPtrFactoryBase();
334   internal::WeakReferenceOwner weak_reference_owner_;
335   uintptr_t ptr_;
336 };
337 }  // namespace internal
338 
339 namespace subtle {
340 
341 // Restricts access to WeakPtrFactory::BindToCurrentSequence() to authorized
342 // callers.
343 class BASE_EXPORT BindWeakPtrFactoryPassKey {
344  private:
345   BindWeakPtrFactoryPassKey() = default;
346 
347   friend class BindWeakPtrFactoryForTesting;
348   friend class performance_manager::FrameNodeImpl;
349   friend class performance_manager::PageNodeImpl;
350   friend class performance_manager::ProcessNodeImpl;
351   friend class performance_manager::WorkerNodeImpl;
352   friend class sequence_manager::internal::TaskQueueImpl;
353 };
354 
355 }  // namespace subtle
356 
357 // A class may be composed of a WeakPtrFactory and thereby
358 // control how it exposes weak pointers to itself.  This is helpful if you only
359 // need weak pointers within the implementation of a class.  This class is also
360 // useful when working with primitive types.  For example, you could have a
361 // WeakPtrFactory<bool> that is used to pass around a weak reference to a bool.
362 template <class T>
363 class WeakPtrFactory : public internal::WeakPtrFactoryBase {
364  public:
365   WeakPtrFactory() = delete;
366 
WeakPtrFactory(T * ptr)367   explicit WeakPtrFactory(T* ptr)
368       : WeakPtrFactoryBase(reinterpret_cast<uintptr_t>(ptr)) {}
369 
370   WeakPtrFactory(const WeakPtrFactory&) = delete;
371   WeakPtrFactory& operator=(const WeakPtrFactory&) = delete;
372 
373   ~WeakPtrFactory() = default;
374 
GetWeakPtr()375   WeakPtr<const T> GetWeakPtr() const {
376     return WeakPtr<const T>(weak_reference_owner_.GetRef(),
377                             reinterpret_cast<const T*>(ptr_));
378   }
379 
GetWeakPtr()380   WeakPtr<T> GetWeakPtr()
381     requires(!std::is_const_v<T>)
382   {
383     return WeakPtr<T>(weak_reference_owner_.GetRef(),
384                       reinterpret_cast<T*>(ptr_));
385   }
386 
GetMutableWeakPtr()387   WeakPtr<T> GetMutableWeakPtr() const
388     requires(!std::is_const_v<T>)
389   {
390     return WeakPtr<T>(weak_reference_owner_.GetRef(),
391                       reinterpret_cast<T*>(ptr_));
392   }
393 
394   // Returns a smart pointer that is valid until the WeakPtrFactory is
395   // invalidated. Unlike WeakPtr, this smart pointer cannot be null, and cannot
396   // be checked to see if the WeakPtrFactory is invalidated. It's intended to
397   // express that the pointer will not (intentionally) outlive the `T` object it
398   // points to, and to crash safely in the case of a bug instead of causing a
399   // use-after-free. This type provides an alternative to WeakPtr to prevent
400   // use-after-free bugs without also introducing "fuzzy lifetimes" that can be
401   // checked for at runtime.
GetSafeRef()402   SafeRef<T> GetSafeRef() const {
403     return internal::MakeSafeRefFromWeakPtrInternals(
404         weak_reference_owner_.GetRef(), reinterpret_cast<T*>(ptr_));
405   }
406 
407   // Call this method to invalidate all existing weak pointers.
InvalidateWeakPtrs()408   void InvalidateWeakPtrs() {
409     DCHECK(ptr_);
410     weak_reference_owner_.Invalidate();
411   }
412 
413   // Call this method to determine if any weak pointers exist.
HasWeakPtrs()414   bool HasWeakPtrs() const {
415     DCHECK(ptr_);
416     return weak_reference_owner_.HasRefs();
417   }
418 
419   // Rebind the factory to the current sequence. This allows creating an object
420   // and associated weak pointers on a different thread from the one they are
421   // used on.
BindToCurrentSequence(subtle::BindWeakPtrFactoryPassKey)422   void BindToCurrentSequence(subtle::BindWeakPtrFactoryPassKey) {
423     weak_reference_owner_.BindToCurrentSequence();
424   }
425 };
426 
427 }  // namespace base
428 
429 #endif  // BASE_MEMORY_WEAK_PTR_H_
430