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