ostd/sync/rcu/non_null/mod.rs
1// SPDX-License-Identifier: MPL-2.0
2
3//! This module provides a trait and some auxiliary types to help abstract and
4//! work with non-null pointers.
5
6mod either;
7
8use core::{marker::PhantomData, mem::ManuallyDrop, ops::Deref, ptr::NonNull};
9
10use crate::prelude::*;
11
12/// A trait that abstracts non-null pointers.
13///
14/// All common smart pointer types such as `Box<T>`, `Arc<T>`, and `Weak<T>`
15/// implement this trait as they can be converted to and from the raw pointer
16/// type of `*const T`.
17///
18/// # Safety
19///
20/// This trait must be implemented correctly (according to the doc comments for
21/// each method). Types like [`Rcu`] rely on this assumption to safely use the
22/// raw pointers.
23///
24/// [`Rcu`]: super::Rcu
25pub unsafe trait NonNullPtr: 'static {
26 /// The target type that this pointer refers to.
27 // TODO: Support `Target: ?Sized`.
28 type Target;
29
30 /// A type that behaves just like a shared reference to the `NonNullPtr`.
31 type Ref<'a>
32 where
33 Self: 'a;
34
35 /// The power of two of the pointer alignment.
36 const ALIGN_BITS: u32;
37
38 /// Converts to a raw pointer.
39 ///
40 /// Each call to `into_raw` must be paired with a call to `from_raw`
41 /// in order to avoid memory leakage.
42 ///
43 /// The lower [`Self::ALIGN_BITS`] of the raw pointer is guaranteed to
44 /// be zero. In other words, the pointer is guaranteed to be aligned to
45 /// `1 << Self::ALIGN_BITS`.
46 fn into_raw(self) -> NonNull<Self::Target>;
47
48 /// Converts back from a raw pointer.
49 ///
50 /// # Safety
51 ///
52 /// 1. The raw pointer must have been previously returned by a call to
53 /// `into_raw`.
54 /// 2. The raw pointer must not be used after calling `from_raw`.
55 ///
56 /// Note that the second point is a hard requirement: Even if the
57 /// resulting value has not (yet) been dropped, the pointer cannot be
58 /// used because it may break Rust aliasing rules (e.g., `Box<T>`
59 /// requires the pointer to be unique and thus _never_ aliased).
60 unsafe fn from_raw(ptr: NonNull<Self::Target>) -> Self;
61
62 /// Obtains a shared reference to the original pointer.
63 ///
64 /// # Safety
65 ///
66 /// The original pointer must outlive the lifetime parameter `'a`, and during `'a`
67 /// no mutable references to the pointer will exist.
68 unsafe fn raw_as_ref<'a>(raw: NonNull<Self::Target>) -> Self::Ref<'a>;
69
70 /// Converts a shared reference to a raw pointer.
71 fn ref_as_raw(ptr_ref: Self::Ref<'_>) -> NonNull<Self::Target>;
72}
73
74/// A type that represents `&'a Box<T>`.
75#[derive(Debug)]
76pub struct BoxRef<'a, T> {
77 inner: *mut T,
78 _marker: PhantomData<&'a T>,
79}
80
81impl<T> Deref for BoxRef<'_, T> {
82 type Target = Box<T>;
83
84 fn deref(&self) -> &Self::Target {
85 // SAFETY: A `Box<T>` is guaranteed to be represented by a single pointer [1] and a shared
86 // reference to the `Box<T>` during the lifetime `'a` can be created according to the
87 // safety requirements of `NonNullPtr::raw_as_ref`.
88 //
89 // [1]: https://doc.rust-lang.org/std/boxed/#memory-layout
90 unsafe { core::mem::transmute(&self.inner) }
91 }
92}
93
94impl<'a, T> BoxRef<'a, T> {
95 /// Dereferences `self` to get a reference to `T` with the lifetime `'a`.
96 pub fn deref_target(&self) -> &'a T {
97 // SAFETY: The reference is created through `NonNullPtr::raw_as_ref`, hence
98 // the original owned pointer and target must outlive the lifetime parameter `'a`,
99 // and during `'a` no mutable references to the pointer will exist.
100 unsafe { &*(self.inner) }
101 }
102}
103
104unsafe impl<T: 'static> NonNullPtr for Box<T> {
105 type Target = T;
106
107 type Ref<'a>
108 = BoxRef<'a, T>
109 where
110 Self: 'a;
111
112 const ALIGN_BITS: u32 = align_of::<T>().trailing_zeros();
113
114 fn into_raw(self) -> NonNull<Self::Target> {
115 let ptr = Box::into_raw(self);
116
117 // SAFETY: The pointer representing a `Box` can never be NULL.
118 unsafe { NonNull::new_unchecked(ptr) }
119 }
120
121 unsafe fn from_raw(ptr: NonNull<Self::Target>) -> Self {
122 let ptr = ptr.as_ptr();
123
124 // SAFETY: The safety is upheld by the caller.
125 unsafe { Box::from_raw(ptr) }
126 }
127
128 unsafe fn raw_as_ref<'a>(raw: NonNull<Self::Target>) -> Self::Ref<'a> {
129 BoxRef {
130 inner: raw.as_ptr(),
131 _marker: PhantomData,
132 }
133 }
134
135 fn ref_as_raw(ptr_ref: Self::Ref<'_>) -> NonNull<Self::Target> {
136 // SAFETY: The pointer representing a `Box` can never be NULL.
137 unsafe { NonNull::new_unchecked(ptr_ref.inner) }
138 }
139}
140
141/// A type that represents `&'a Arc<T>`.
142#[derive(Debug)]
143pub struct ArcRef<'a, T> {
144 inner: ManuallyDrop<Arc<T>>,
145 _marker: PhantomData<&'a Arc<T>>,
146}
147
148impl<T> Deref for ArcRef<'_, T> {
149 type Target = Arc<T>;
150
151 fn deref(&self) -> &Self::Target {
152 &self.inner
153 }
154}
155
156impl<'a, T> ArcRef<'a, T> {
157 /// Dereferences `self` to get a reference to `T` with the lifetime `'a`.
158 pub fn deref_target(&self) -> &'a T {
159 // SAFETY: The reference is created through `NonNullPtr::raw_as_ref`, hence
160 // the original owned pointer and target must outlive the lifetime parameter `'a`,
161 // and during `'a` no mutable references to the pointer will exist.
162 unsafe { &*(self.deref().deref() as *const T) }
163 }
164}
165
166unsafe impl<T: 'static> NonNullPtr for Arc<T> {
167 type Target = T;
168
169 type Ref<'a>
170 = ArcRef<'a, T>
171 where
172 Self: 'a;
173
174 const ALIGN_BITS: u32 = align_of::<T>().trailing_zeros();
175
176 fn into_raw(self) -> NonNull<Self::Target> {
177 let ptr = Arc::into_raw(self).cast_mut();
178
179 // SAFETY: The pointer representing an `Arc` can never be NULL.
180 unsafe { NonNull::new_unchecked(ptr) }
181 }
182
183 unsafe fn from_raw(ptr: NonNull<Self::Target>) -> Self {
184 let ptr = ptr.as_ptr().cast_const();
185
186 // SAFETY: The safety is upheld by the caller.
187 unsafe { Arc::from_raw(ptr) }
188 }
189
190 unsafe fn raw_as_ref<'a>(raw: NonNull<Self::Target>) -> Self::Ref<'a> {
191 // SAFETY: The safety is upheld by the caller.
192 unsafe {
193 ArcRef {
194 inner: ManuallyDrop::new(Arc::from_raw(raw.as_ptr())),
195 _marker: PhantomData,
196 }
197 }
198 }
199
200 fn ref_as_raw(ptr_ref: Self::Ref<'_>) -> NonNull<Self::Target> {
201 NonNullPtr::into_raw(ManuallyDrop::into_inner(ptr_ref.inner))
202 }
203}