Skip to main content

atomic_tagged_ptr/
ptr.rs

1use crate::traits::IntoOptionNonNull;
2use core::fmt;
3use core::ptr::NonNull;
4
5/// A transparent wrapper around `Option<NonNull<T>>` returned by `AtomicTaggedPtr` operations.
6///
7/// It provides convenient helper methods to convert into raw const/mutable pointers,
8/// access the underlying `Option<NonNull<T>>`, and supports direct comparisons.
9#[repr(transparent)]
10pub struct Ptr<T> {
11    inner: Option<NonNull<T>>,
12}
13
14impl<T> Default for Ptr<T> {
15    #[inline]
16    fn default() -> Self {
17        Self { inner: None }
18    }
19}
20
21impl<T> Copy for Ptr<T> {}
22
23impl<T> Clone for Ptr<T> {
24    #[inline]
25    fn clone(&self) -> Self {
26        *self
27    }
28}
29
30impl<T> fmt::Debug for Ptr<T> {
31    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
32        fmt::Debug::fmt(&self.inner, f)
33    }
34}
35
36impl<T> Ptr<T> {
37    /// Creates a new `Ptr` wrapper from an `Option<NonNull<T>>`.
38    #[inline]
39    pub const fn new(ptr: Option<NonNull<T>>) -> Self {
40        Self { inner: ptr }
41    }
42
43    /// Converts the pointer into a raw mutable pointer `*mut T`.
44    /// Returns a null pointer if the underlying value is `None`.
45    #[inline]
46    pub fn as_mut_ptr(self) -> *mut T {
47        self.inner
48            .map(|p| p.as_ptr())
49            .unwrap_or(core::ptr::null_mut())
50    }
51
52    /// Converts the pointer into a raw const pointer `*const T`.
53    /// Returns a null pointer if the underlying value is `None`.
54    #[inline]
55    pub fn as_ptr(self) -> *const T {
56        self.inner
57            .map(|p| p.as_ptr() as *const T)
58            .unwrap_or(core::ptr::null())
59    }
60
61    /// Obtains the underlying `Option<NonNull<T>>`.
62    #[inline]
63    pub const fn option(self) -> Option<NonNull<T>> {
64        self.inner
65    }
66
67    /// Obtains the underlying `Option<NonNull<T>>`.
68    #[inline]
69    pub const fn as_option(self) -> Option<NonNull<T>> {
70        self.inner
71    }
72
73    /// Returns `true` if the pointer is null.
74    #[inline]
75    pub fn is_null(self) -> bool {
76        self.inner.is_none()
77    }
78
79    /// Returns `true` if the pointer is not null (is some).
80    #[inline]
81    pub fn is_some(self) -> bool {
82        self.inner.is_some()
83    }
84
85    /// Returns `true` if the pointer is null (is none).
86    #[inline]
87    pub fn is_none(self) -> bool {
88        self.inner.is_none()
89    }
90}
91
92// --- PartialEq implementations to ensure seamless forward compatibility ---
93
94impl<T> PartialEq for Ptr<T> {
95    #[inline]
96    fn eq(&self, other: &Self) -> bool {
97        self.inner == other.inner
98    }
99}
100
101impl<T> Eq for Ptr<T> {}
102
103impl<T> core::hash::Hash for Ptr<T> {
104    #[inline]
105    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
106        self.inner.hash(state);
107    }
108}
109
110impl<T> PartialEq<Option<NonNull<T>>> for Ptr<T> {
111    #[inline]
112    fn eq(&self, other: &Option<NonNull<T>>) -> bool {
113        self.inner == *other
114    }
115}
116
117impl<T> PartialEq<NonNull<T>> for Ptr<T> {
118    #[inline]
119    fn eq(&self, other: &NonNull<T>) -> bool {
120        self.inner == Some(*other)
121    }
122}
123
124impl<T> PartialEq<*const T> for Ptr<T> {
125    #[inline]
126    fn eq(&self, other: &*const T) -> bool {
127        self.as_ptr() == *other
128    }
129}
130
131impl<T> PartialEq<*mut T> for Ptr<T> {
132    #[inline]
133    fn eq(&self, other: &*mut T) -> bool {
134        self.as_mut_ptr() == *other
135    }
136}
137
138// Enable Ptr<T> to be directly passed into AtomicTaggedPtr APIs
139impl<T> IntoOptionNonNull<T> for Ptr<T> {
140    #[inline]
141    fn into_option_non_null(self) -> Option<NonNull<T>> {
142        self.inner
143    }
144}
145
146/// A packaged representation of a pointer and a generation tag.
147/// Used for atomic operations with `AtomicTaggedPtr`.
148#[derive(PartialEq, Eq, Hash)]
149pub struct TaggedPtr<T> {
150    /// The physical pointer wrapper.
151    pub ptr: Ptr<T>,
152    /// The generation tag for ABA protection.
153    pub tag: crate::Tag,
154}
155
156impl<T> Copy for TaggedPtr<T> {}
157
158impl<T> Clone for TaggedPtr<T> {
159    #[inline]
160    fn clone(&self) -> Self {
161        *self
162    }
163}
164
165impl<T> Default for TaggedPtr<T> {
166    #[inline]
167    fn default() -> Self {
168        Self {
169            ptr: Ptr::default(),
170            tag: crate::Tag::default(),
171        }
172    }
173}
174
175impl<T> TaggedPtr<T> {
176    /// Creates a new `TaggedPtr` from a pointer and a tag.
177    #[inline]
178    pub fn new<P>(ptr: P, tag: crate::Tag) -> Self
179    where
180        P: IntoOptionNonNull<T>,
181    {
182        Self {
183            ptr: Ptr::new(ptr.into_option_non_null()),
184            tag,
185        }
186    }
187
188    /// Deconstructs the `TaggedPtr` into a tuple of `(Ptr<T>, Tag)`.
189    #[inline]
190    pub fn decompose(self) -> (Ptr<T>, crate::Tag) {
191        (self.ptr, self.tag)
192    }
193}
194
195impl<T> fmt::Debug for TaggedPtr<T> {
196    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
197        f.debug_struct("TaggedPtr")
198            .field("ptr", &self.ptr)
199            .field("tag", &self.tag)
200            .finish()
201    }
202}
203
204impl<T> From<(Ptr<T>, crate::Tag)> for TaggedPtr<T> {
205    #[inline]
206    fn from(tuple: (Ptr<T>, crate::Tag)) -> Self {
207        Self {
208            ptr: tuple.0,
209            tag: tuple.1,
210        }
211    }
212}
213
214impl<T> From<(Option<NonNull<T>>, crate::Tag)> for TaggedPtr<T> {
215    #[inline]
216    fn from(tuple: (Option<NonNull<T>>, crate::Tag)) -> Self {
217        Self {
218            ptr: Ptr::new(tuple.0),
219            tag: tuple.1,
220        }
221    }
222}
223
224impl<T> From<TaggedPtr<T>> for (Ptr<T>, crate::Tag) {
225    #[inline]
226    fn from(tagged: TaggedPtr<T>) -> Self {
227        (tagged.ptr, tagged.tag)
228    }
229}
230
231impl<T> IntoOptionNonNull<T> for TaggedPtr<T> {
232    #[inline]
233    fn into_option_non_null(self) -> Option<NonNull<T>> {
234        self.ptr.into_option_non_null()
235    }
236}