tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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_