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}