xref: /aosp_15_r20/external/cronet/base/memory/safe_ref.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2021 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #ifndef BASE_MEMORY_SAFE_REF_H_
6*6777b538SAndroid Build Coastguard Worker #define BASE_MEMORY_SAFE_REF_H_
7*6777b538SAndroid Build Coastguard Worker 
8*6777b538SAndroid Build Coastguard Worker #include <compare>
9*6777b538SAndroid Build Coastguard Worker #include <concepts>
10*6777b538SAndroid Build Coastguard Worker #include <utility>
11*6777b538SAndroid Build Coastguard Worker 
12*6777b538SAndroid Build Coastguard Worker #include "base/check.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/memory/safe_ref_traits.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/memory/weak_ptr.h"
15*6777b538SAndroid Build Coastguard Worker 
16*6777b538SAndroid Build Coastguard Worker namespace base {
17*6777b538SAndroid Build Coastguard Worker 
18*6777b538SAndroid Build Coastguard Worker // SafeRef smart pointers are used to represent a non-owning pointer to an
19*6777b538SAndroid Build Coastguard Worker // object, where the pointer is always intended to be valid. These are useful in
20*6777b538SAndroid Build Coastguard Worker // the same cases that a raw pointer `T*` (or a `T&`) would traditionally be
21*6777b538SAndroid Build Coastguard Worker // used, as the owner of the SafeRef knows the lifetime of the pointed-to object
22*6777b538SAndroid Build Coastguard Worker // from other means and will not use the pointer after the pointed-to object is
23*6777b538SAndroid Build Coastguard Worker // destroyed. However, unlike a `T*` or `T&`, a logic bug will manifest as a
24*6777b538SAndroid Build Coastguard Worker // benign crash instead of as a Use-after-Free.
25*6777b538SAndroid Build Coastguard Worker //
26*6777b538SAndroid Build Coastguard Worker // SafeRef pointers cannot be null (as expressed by the "Ref" suffix instead of
27*6777b538SAndroid Build Coastguard Worker // "Ptr"). A SafeRef can be wrapped in an std::optional if it should not always
28*6777b538SAndroid Build Coastguard Worker // point to something valid. (A SafePtr sibling type can be introduced if this
29*6777b538SAndroid Build Coastguard Worker // is problematic, or if consuming moves are needed!)
30*6777b538SAndroid Build Coastguard Worker //
31*6777b538SAndroid Build Coastguard Worker // If code wants to track the lifetime of the object directly through its
32*6777b538SAndroid Build Coastguard Worker // pointer, and dynamically handle the case of the pointer outliving the object
33*6777b538SAndroid Build Coastguard Worker // it points to, then base::WeakPtr should be used instead.
34*6777b538SAndroid Build Coastguard Worker //
35*6777b538SAndroid Build Coastguard Worker // The SafeRef pointer is constructed from a base::WeakPtrFactory's GetSafeRef()
36*6777b538SAndroid Build Coastguard Worker // method. Since it is tied to the base::WeakPtrFactory, it will consider its
37*6777b538SAndroid Build Coastguard Worker // pointee invalid when the base::WeakPtrFactory is invalidated, in the same way
38*6777b538SAndroid Build Coastguard Worker // as base::WeakPtr does, including after a call to InvalidateWeakPtrs().
39*6777b538SAndroid Build Coastguard Worker //
40*6777b538SAndroid Build Coastguard Worker // SafeRefTraits are only meant to mark SafeRefs that were found to be dangling,
41*6777b538SAndroid Build Coastguard Worker // thus one should not use this flag to disable dangling pointer detection on
42*6777b538SAndroid Build Coastguard Worker // SafeRef. This parameter is set to SafeRefTraits::kEmpty by default.
43*6777b538SAndroid Build Coastguard Worker //
44*6777b538SAndroid Build Coastguard Worker // THREAD SAFETY: SafeRef pointers (like base::WeakPtr) may only be used on the
45*6777b538SAndroid Build Coastguard Worker // sequence (or thread) where the associated base::WeakPtrFactory will be
46*6777b538SAndroid Build Coastguard Worker // invalidated and/or destroyed. They are safe to passively hold or to destroy
47*6777b538SAndroid Build Coastguard Worker // on any thread though.
48*6777b538SAndroid Build Coastguard Worker //
49*6777b538SAndroid Build Coastguard Worker // This class is expected to one day be replaced by a more flexible and safe
50*6777b538SAndroid Build Coastguard Worker // smart pointer abstraction which is not tied to base::WeakPtrFactory, such as
51*6777b538SAndroid Build Coastguard Worker // raw_ptr<T> from the MiraclePtr project (though perhaps a non-nullable raw_ref
52*6777b538SAndroid Build Coastguard Worker // equivalent).
53*6777b538SAndroid Build Coastguard Worker template <typename T, SafeRefTraits Traits /*= SafeRefTraits::kEmpty*/>
54*6777b538SAndroid Build Coastguard Worker class SafeRef {
55*6777b538SAndroid Build Coastguard Worker  public:
56*6777b538SAndroid Build Coastguard Worker   // No default constructor, since there's no null state. Use an optional
57*6777b538SAndroid Build Coastguard Worker   // SafeRef if the pointer may not be present.
58*6777b538SAndroid Build Coastguard Worker 
59*6777b538SAndroid Build Coastguard Worker   // Copy construction and assignment.
SafeRef(const SafeRef & other)60*6777b538SAndroid Build Coastguard Worker   SafeRef(const SafeRef& other) : ref_(other.ref_), ptr_(other.ptr_) {
61*6777b538SAndroid Build Coastguard Worker     // Avoid use-after-move.
62*6777b538SAndroid Build Coastguard Worker     CHECK(ref_.IsValid());
63*6777b538SAndroid Build Coastguard Worker   }
64*6777b538SAndroid Build Coastguard Worker   SafeRef& operator=(const SafeRef& other) {
65*6777b538SAndroid Build Coastguard Worker     ref_ = other.ref_;
66*6777b538SAndroid Build Coastguard Worker     ptr_ = other.ptr_;
67*6777b538SAndroid Build Coastguard Worker     // Avoid use-after-move.
68*6777b538SAndroid Build Coastguard Worker     CHECK(ref_.IsValid());
69*6777b538SAndroid Build Coastguard Worker     return *this;
70*6777b538SAndroid Build Coastguard Worker   }
71*6777b538SAndroid Build Coastguard Worker 
72*6777b538SAndroid Build Coastguard Worker   // Move construction and assignment.
SafeRef(SafeRef && other)73*6777b538SAndroid Build Coastguard Worker   SafeRef(SafeRef&& other)
74*6777b538SAndroid Build Coastguard Worker       : ref_(std::move(other.ref_)), ptr_(std::move(other.ptr_)) {
75*6777b538SAndroid Build Coastguard Worker     // Avoid use-after-move.
76*6777b538SAndroid Build Coastguard Worker     CHECK(ref_.IsValid());
77*6777b538SAndroid Build Coastguard Worker   }
78*6777b538SAndroid Build Coastguard Worker   SafeRef& operator=(SafeRef&& other) {
79*6777b538SAndroid Build Coastguard Worker     ref_ = std::move(other.ref_);
80*6777b538SAndroid Build Coastguard Worker     ptr_ = std::move(other.ptr_);
81*6777b538SAndroid Build Coastguard Worker     // Avoid use-after-move.
82*6777b538SAndroid Build Coastguard Worker     CHECK(ref_.IsValid());
83*6777b538SAndroid Build Coastguard Worker     return *this;
84*6777b538SAndroid Build Coastguard Worker   }
85*6777b538SAndroid Build Coastguard Worker 
86*6777b538SAndroid Build Coastguard Worker   // Copy conversion from SafeRef<U>.
87*6777b538SAndroid Build Coastguard Worker   template <typename U>
requires(std::convertible_to<U *,T * >)88*6777b538SAndroid Build Coastguard Worker     requires(std::convertible_to<U*, T*>)
89*6777b538SAndroid Build Coastguard Worker   // NOLINTNEXTLINE(google-explicit-constructor)
90*6777b538SAndroid Build Coastguard Worker   SafeRef(const SafeRef<U>& other)
91*6777b538SAndroid Build Coastguard Worker       : ref_(other.ref_),
92*6777b538SAndroid Build Coastguard Worker         ptr_(other.ptr_)  // raw_ptr<U> converts to raw_ptr<T>.
93*6777b538SAndroid Build Coastguard Worker   {
94*6777b538SAndroid Build Coastguard Worker     // Avoid use-after-move.
95*6777b538SAndroid Build Coastguard Worker     CHECK(ref_.IsValid());
96*6777b538SAndroid Build Coastguard Worker   }
97*6777b538SAndroid Build Coastguard Worker   template <typename U>
98*6777b538SAndroid Build Coastguard Worker   SafeRef& operator=(const SafeRef<U>& other) {
99*6777b538SAndroid Build Coastguard Worker     ref_ = other.ref_;
100*6777b538SAndroid Build Coastguard Worker     ptr_ = other.ptr_;  // raw_ptr<U> converts to raw_ptr<T>.
101*6777b538SAndroid Build Coastguard Worker     // Avoid use-after-move.
102*6777b538SAndroid Build Coastguard Worker     CHECK(ref_.IsValid());
103*6777b538SAndroid Build Coastguard Worker     return *this;
104*6777b538SAndroid Build Coastguard Worker   }
105*6777b538SAndroid Build Coastguard Worker 
106*6777b538SAndroid Build Coastguard Worker   // Move conversion from SafeRef<U>.
107*6777b538SAndroid Build Coastguard Worker   template <typename U>
108*6777b538SAndroid Build Coastguard Worker   // NOLINTNEXTLINE(google-explicit-constructor)
SafeRef(SafeRef<U> && other)109*6777b538SAndroid Build Coastguard Worker   SafeRef(SafeRef<U>&& other)
110*6777b538SAndroid Build Coastguard Worker       : ref_(std::move(other.ref_)),
111*6777b538SAndroid Build Coastguard Worker         ptr_(std::move(other.ptr_))  // raw_ptr<U> converts to raw_ptr<T>.
112*6777b538SAndroid Build Coastguard Worker   {
113*6777b538SAndroid Build Coastguard Worker     // Avoid use-after-move.
114*6777b538SAndroid Build Coastguard Worker     CHECK(ref_.IsValid());
115*6777b538SAndroid Build Coastguard Worker   }
116*6777b538SAndroid Build Coastguard Worker   template <typename U>
117*6777b538SAndroid Build Coastguard Worker   SafeRef& operator=(SafeRef<U>&& other) {
118*6777b538SAndroid Build Coastguard Worker     ref_ = std::move(other.ref_);
119*6777b538SAndroid Build Coastguard Worker     ptr_ = std::move(other.ptr_);  // raw_ptr<U> converts to raw_ptr<T>.
120*6777b538SAndroid Build Coastguard Worker     // Avoid use-after-move.
121*6777b538SAndroid Build Coastguard Worker     CHECK(ref_.IsValid());
122*6777b538SAndroid Build Coastguard Worker     return *this;
123*6777b538SAndroid Build Coastguard Worker   }
124*6777b538SAndroid Build Coastguard Worker 
125*6777b538SAndroid Build Coastguard Worker   // Ordered by the pointer, not the pointee.
126*6777b538SAndroid Build Coastguard Worker   template <typename U>
127*6777b538SAndroid Build Coastguard Worker   std::strong_ordering operator<=>(const SafeRef<U>& other) const {
128*6777b538SAndroid Build Coastguard Worker     return ptr_ <=> other.ptr_;
129*6777b538SAndroid Build Coastguard Worker   }
130*6777b538SAndroid Build Coastguard Worker 
131*6777b538SAndroid Build Coastguard Worker   // Provide access to the underlying T as a reference. Will CHECK() if the T
132*6777b538SAndroid Build Coastguard Worker   // pointee is no longer alive.
133*6777b538SAndroid Build Coastguard Worker   T& operator*() const {
134*6777b538SAndroid Build Coastguard Worker     CHECK(ref_.IsValid());
135*6777b538SAndroid Build Coastguard Worker     return *ptr_;
136*6777b538SAndroid Build Coastguard Worker   }
137*6777b538SAndroid Build Coastguard Worker 
138*6777b538SAndroid Build Coastguard Worker   // Used to call methods on the underlying T. Will CHECK() if the T pointee is
139*6777b538SAndroid Build Coastguard Worker   // no longer alive.
140*6777b538SAndroid Build Coastguard Worker   T* operator->() const {
141*6777b538SAndroid Build Coastguard Worker     CHECK(ref_.IsValid());
142*6777b538SAndroid Build Coastguard Worker     return &*ptr_;
143*6777b538SAndroid Build Coastguard Worker   }
144*6777b538SAndroid Build Coastguard Worker 
145*6777b538SAndroid Build Coastguard Worker  private:
146*6777b538SAndroid Build Coastguard Worker   template <typename U, SafeRefTraits PassedTraits>
147*6777b538SAndroid Build Coastguard Worker   friend class SafeRef;
148*6777b538SAndroid Build Coastguard Worker   template <typename U>
149*6777b538SAndroid Build Coastguard Worker   friend SafeRef<U> internal::MakeSafeRefFromWeakPtrInternals(
150*6777b538SAndroid Build Coastguard Worker       internal::WeakReference&& ref,
151*6777b538SAndroid Build Coastguard Worker       U* ptr);
152*6777b538SAndroid Build Coastguard Worker 
153*6777b538SAndroid Build Coastguard Worker   // Construction from a from a WeakPtr's internals. Will CHECK() if the WeakPtr
154*6777b538SAndroid Build Coastguard Worker   // is already invalid.
SafeRef(internal::WeakReference && ref,T * ptr)155*6777b538SAndroid Build Coastguard Worker   explicit SafeRef(internal::WeakReference&& ref, T* ptr)
156*6777b538SAndroid Build Coastguard Worker       : ref_(std::move(ref)), ptr_(ptr) {
157*6777b538SAndroid Build Coastguard Worker     CHECK(ref_.IsValid());
158*6777b538SAndroid Build Coastguard Worker   }
159*6777b538SAndroid Build Coastguard Worker 
160*6777b538SAndroid Build Coastguard Worker   internal::WeakReference ref_;
161*6777b538SAndroid Build Coastguard Worker 
162*6777b538SAndroid Build Coastguard Worker   static constexpr RawPtrTraits PtrTrait = Traits == SafeRefTraits::kEmpty
163*6777b538SAndroid Build Coastguard Worker                                                ? RawPtrTraits::kEmpty
164*6777b538SAndroid Build Coastguard Worker                                                : DanglingUntriaged;
165*6777b538SAndroid Build Coastguard Worker   // This pointer is only valid when ref_.is_valid() is true.  Otherwise, its
166*6777b538SAndroid Build Coastguard Worker   // value is undefined (as opposed to nullptr). Unlike WeakPtr, this raw_ptr is
167*6777b538SAndroid Build Coastguard Worker   // not allowed to dangle.
168*6777b538SAndroid Build Coastguard Worker   raw_ptr<T, PtrTrait> ptr_;
169*6777b538SAndroid Build Coastguard Worker };
170*6777b538SAndroid Build Coastguard Worker 
171*6777b538SAndroid Build Coastguard Worker namespace internal {
172*6777b538SAndroid Build Coastguard Worker template <typename T>
MakeSafeRefFromWeakPtrInternals(internal::WeakReference && ref,T * ptr)173*6777b538SAndroid Build Coastguard Worker SafeRef<T> MakeSafeRefFromWeakPtrInternals(internal::WeakReference&& ref,
174*6777b538SAndroid Build Coastguard Worker                                            T* ptr) {
175*6777b538SAndroid Build Coastguard Worker   return SafeRef<T>(std::move(ref), ptr);
176*6777b538SAndroid Build Coastguard Worker }
177*6777b538SAndroid Build Coastguard Worker }  // namespace internal
178*6777b538SAndroid Build Coastguard Worker 
179*6777b538SAndroid Build Coastguard Worker }  // namespace base
180*6777b538SAndroid Build Coastguard Worker 
181*6777b538SAndroid Build Coastguard Worker #endif  // BASE_MEMORY_SAFE_REF_H_
182