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