safe_ref.h 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. // 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. #ifndef BASE_MEMORY_SAFE_REF_H_
  5. #define BASE_MEMORY_SAFE_REF_H_
  6. #include "base/check.h"
  7. #include "base/memory/weak_ptr.h"
  8. #include <utility>
  9. namespace base {
  10. // SafeRef smart pointers are used to represent a non-owning pointer to an
  11. // object, where the pointer is always intended to be valid. These are useful in
  12. // the same cases that a raw pointer `T*` (or a `T&`) would traditionally be
  13. // used, as the owner of the SafeRef knows the lifetime of the pointed-to object
  14. // from other means and will not use the pointer after the pointed-to object is
  15. // destroyed. However, unlike a `T*` or `T&`, a logic bug will manifest as a
  16. // benign crash instead of as a Use-after-Free.
  17. //
  18. // SafeRef pointers can not be null (as expressed by the "Ref" suffix instead of
  19. // "Ptr"). A SafeRef can be wrapped in an absl::optional if it should not always
  20. // point to something valid. (A SafePtr sibling type can be introduced if this
  21. // is problematic, or if consuming moves are needed!)
  22. //
  23. // If code wants to track the lifetime of the object directly through its
  24. // pointer, and dynamically handle the case of the pointer outliving the object
  25. // it points to, then base::WeakPtr should be used instead.
  26. //
  27. // The SafeRef pointer is constructed from a base::WeakPtrFactory's GetSafeRef()
  28. // method. Since it is tied to the base::WeakPtrFactory, it will consider its
  29. // pointee invalid when the base::WeakPtrFactory is invalidated, in the same way
  30. // as base::WeakPtr does, including after a call to InvalidateWeakPtrs().
  31. //
  32. // THREAD SAFETY: SafeRef pointers (like base::WeakPtr) may only be used on the
  33. // sequence (or thread) where the associated base::WeakPtrFactory will be
  34. // invalidated and/or destroyed. They are safe to passively hold or to destroy
  35. // on any thread though.
  36. //
  37. // This class is expected to one day be replaced by a more flexible and safe
  38. // smart pointer abstraction which is not tied to base::WeakPtrFactory, such as
  39. // raw_ptr<T> from the MiraclePtr project (though perhaps a non-nullable raw_ref
  40. // equivalent).
  41. template <typename T>
  42. class SafeRef {
  43. public:
  44. // No default constructor, since there's no null state. Use an optional
  45. // SafeRef if the pointer may not be present.
  46. // Copy construction and assignment.
  47. SafeRef(const SafeRef& p) : w_(p.w_) {
  48. // Avoid use-after-move.
  49. CHECK(w_);
  50. }
  51. SafeRef& operator=(const SafeRef& p) {
  52. w_ = p.w_;
  53. // Avoid use-after-move.
  54. CHECK(w_);
  55. return *this;
  56. }
  57. // Move construction and assignment.
  58. SafeRef(SafeRef&& p) : w_(std::move(p.w_)) { CHECK(w_); }
  59. SafeRef& operator=(SafeRef&& p) {
  60. w_ = std::move(p.w_);
  61. // Avoid use-after-move.
  62. CHECK(w_);
  63. return *this;
  64. }
  65. // Copy conversion from SafeRef<U>.
  66. template <typename U>
  67. // NOLINTNEXTLINE(google-explicit-constructor)
  68. SafeRef(const SafeRef<U>& p) : w_(p.w_) {
  69. // Avoid use-after-move.
  70. CHECK(w_);
  71. }
  72. template <typename U>
  73. SafeRef& operator=(const SafeRef<U>& p) {
  74. w_ = p.w_;
  75. // Avoid use-after-move.
  76. CHECK(w_);
  77. return *this;
  78. }
  79. // Move conversion from SafeRef<U>.
  80. template <typename U>
  81. // NOLINTNEXTLINE(google-explicit-constructor)
  82. SafeRef(SafeRef<U>&& p) : w_(std::move(p.w_)) {
  83. // Avoid use-after-move.
  84. CHECK(w_);
  85. }
  86. template <typename U>
  87. SafeRef& operator=(SafeRef<U>&& p) {
  88. w_ = std::move(p.w_);
  89. // Avoid use-after-move.
  90. CHECK(w_);
  91. return *this;
  92. }
  93. // Call methods on the underlying T. Will CHECK() if the T pointee is no
  94. // longer alive.
  95. T* operator->() const {
  96. // We rely on WeakPtr<T> to CHECK() on a bad deref; tests verify this.
  97. return w_.operator->();
  98. }
  99. // Provide access to the underlying T as a reference. Will CHECK() if the T
  100. // pointee is no longer alive.
  101. T& operator*() const { return *operator->(); }
  102. private:
  103. template <typename U>
  104. friend class SafeRef;
  105. template <typename U>
  106. friend SafeRef<U> internal::MakeSafeRefFromWeakPtrInternals(
  107. const internal::WeakReference& ref,
  108. U* ptr);
  109. // Construction from a from WeakPtr. Will CHECK() if the WeakPtr is already
  110. // invalid.
  111. explicit SafeRef(WeakPtr<T> w) : w_(std::move(w)) { CHECK(w_); }
  112. WeakPtr<T> w_;
  113. };
  114. namespace internal {
  115. template <typename T>
  116. SafeRef<T> MakeSafeRefFromWeakPtrInternals(const internal::WeakReference& ref,
  117. T* ptr) {
  118. CHECK(ptr);
  119. return SafeRef<T>(WeakPtr<T>(ref, ptr));
  120. }
  121. } // namespace internal
  122. } // namespace base
  123. #endif // BASE_MEMORY_SAFE_REF_H_