blob: 97c2c1ea02266e56999dd8a4ccdeed4f5e810bac [file] [log] [blame]
danakj45c91782021-09-29 18:23:571// Copyright (c) 2021 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef BASE_MEMORY_SAFE_REF_H_
6#define BASE_MEMORY_SAFE_REF_H_
7
8#include "base/check.h"
9#include "base/memory/weak_ptr.h"
10
11#include <utility>
12
13namespace base {
14
15// SafeRef smart pointers are used to represent a non-owning pointer to an
16// object, where the pointer is always intended to be valid. These are useful in
17// the same cases that a raw pointer `T*` (or a `T&`) would traditionally be
18// used, as the owner of the SafeRef knows the lifetime of the pointed-to object
19// from other means and will not use the pointer after the pointed-to object is
20// destroyed. However, unlike a `T*` or `T&`, a logic bug will manifest as a
21// benign crash instead of as a Use-after-Free.
22//
23// SafeRef pointers can not be null (as expressed by the "Ref" suffix instead of
24// "Ptr"). A SafeRef can be wrapped in an absl::optional if it should not always
25// point to something valid. (A SafePtr sibling type can be introduced if this
26// is problematic, or if consuming moves are needed!)
27//
28// If code wants to track the lifetime of the object directly through its
29// pointer, and dynamically handle the case of the pointer outliving the object
30// it points to, then base::WeakPtr should be used instead.
31//
32// The SafeRef pointer is constructed from a base::WeakPtrFactory's GetSafeRef()
33// method. Since it is tied to the base::WeakPtrFactory, it will consider its
34// pointee invalid when the base::WeakPtrFactory is invalidated, in the same way
35// as base::WeakPtr does, including after a call to InvalidateWeakPtrs().
36//
37// THREAD SAFETY: SafeRef pointers (like base::WeakPtr) may only be used on the
38// sequence (or thread) where the associated base::WeakPtrFactory will be
39// invalidated and/or destroyed. They are safe to passively hold or to destroy
40// on any thread though.
41//
42// This class is expected to one day be replaced by a more flexible and safe
43// smart pointer abstraction which is not tied to base::WeakPtrFactory, such as
44// raw_ptr<T> from the MiraclePtr project (though perhaps a non-nullable raw_ref
45// equivalent).
46template <typename T>
47class SafeRef {
48 public:
49 // No default constructor, since there's no null state. Use an optional
Daniel Chenge31a1bf72022-07-13 20:18:0250 // SafeRef if the pointer may not be present.
danakj45c91782021-09-29 18:23:5751
52 // Copy construction and assignment.
Daniel Chenge31a1bf72022-07-13 20:18:0253 SafeRef(const SafeRef& p) : w_(p.w_) {
54 // Avoid use-after-move.
55 CHECK(w_);
56 }
danakj45c91782021-09-29 18:23:5757 SafeRef& operator=(const SafeRef& p) {
58 w_ = p.w_;
Daniel Chenge31a1bf72022-07-13 20:18:0259 // Avoid use-after-move.
60 CHECK(w_);
danakj45c91782021-09-29 18:23:5761 return *this;
62 }
63
Daniel Chenge31a1bf72022-07-13 20:18:0264 // Move construction and assignment.
65 SafeRef(SafeRef&& p) : w_(std::move(p.w_)) { CHECK(w_); }
66 SafeRef& operator=(SafeRef&& p) {
67 w_ = std::move(p.w_);
68 // Avoid use-after-move.
69 CHECK(w_);
70 return *this;
71 }
72
73 // Copy conversion from SafeRef<U>.
danakj45c91782021-09-29 18:23:5774 template <typename U>
Daniel Chenge31a1bf72022-07-13 20:18:0275 // NOLINTNEXTLINE(google-explicit-constructor)
76 SafeRef(const SafeRef<U>& p) : w_(p.w_) {
77 // Avoid use-after-move.
78 CHECK(w_);
79 }
danakj45c91782021-09-29 18:23:5780 template <typename U>
81 SafeRef& operator=(const SafeRef<U>& p) {
82 w_ = p.w_;
Daniel Chenge31a1bf72022-07-13 20:18:0283 // Avoid use-after-move.
84 CHECK(w_);
85 return *this;
86 }
87
88 // Move conversion from SafeRef<U>.
89 template <typename U>
90 // NOLINTNEXTLINE(google-explicit-constructor)
91 SafeRef(SafeRef<U>&& p) : w_(std::move(p.w_)) {
92 // Avoid use-after-move.
93 CHECK(w_);
94 }
95 template <typename U>
96 SafeRef& operator=(SafeRef<U>&& p) {
97 w_ = std::move(p.w_);
98 // Avoid use-after-move.
99 CHECK(w_);
danakj45c91782021-09-29 18:23:57100 return *this;
101 }
102
103 // Call methods on the underlying T. Will CHECK() if the T pointee is no
104 // longer alive.
Eric Orth6b0aab52021-09-30 22:29:34105 T* operator->() const {
danakj45c91782021-09-29 18:23:57106 // We rely on WeakPtr<T> to CHECK() on a bad deref; tests verify this.
107 return w_.operator->();
108 }
109
110 // Provide access to the underlying T as a reference. Will CHECK() if the T
111 // pointee is no longer alive.
Eric Orth6b0aab52021-09-30 22:29:34112 T& operator*() const { return *operator->(); }
danakj45c91782021-09-29 18:23:57113
114 private:
115 template <typename U>
116 friend class SafeRef;
Stephan Hartmanna951ccf72021-10-06 18:06:31117 template <typename U>
118 friend SafeRef<U> internal::MakeSafeRefFromWeakPtrInternals(
danakj45c91782021-09-29 18:23:57119 const internal::WeakReference& ref,
Stephan Hartmanna951ccf72021-10-06 18:06:31120 U* ptr);
danakj45c91782021-09-29 18:23:57121
122 // Construction from a from WeakPtr. Will CHECK() if the WeakPtr is already
123 // invalid.
124 explicit SafeRef(WeakPtr<T> w) : w_(std::move(w)) { CHECK(w_); }
125
126 WeakPtr<T> w_;
127};
128
129namespace internal {
130template <typename T>
131SafeRef<T> MakeSafeRefFromWeakPtrInternals(const internal::WeakReference& ref,
132 T* ptr) {
133 CHECK(ptr);
134 return SafeRef<T>(WeakPtr<T>(ref, ptr));
135}
136} // namespace internal
137
138} // namespace base
139
140#endif // BASE_MEMORY_SAFE_REF_H_