1use core::sync::atomic::{AtomicPtr, Ordering};
6
7pub trait ToMutPtr {
9 type Target: ?Sized;
11
12 fn to_mut_ptr(&self) -> *mut Self::Target;
14}
15
16impl<T: ?Sized> ToMutPtr for T {
17 type Target = T;
18
19 #[inline(always)]
20 fn to_mut_ptr(&self) -> *mut T {
21 self as *const T as *mut T
22 }
23}
24
25#[repr(transparent)]
31pub struct AtomicConstPtr<T> {
32 inner: AtomicPtr<T>,
33}
34
35impl<T> AtomicConstPtr<T> {
36 #[inline]
38 pub const fn new(ptr: *const T) -> Self {
39 Self { inner: AtomicPtr::new(ptr.cast_mut()) }
40 }
41
42 #[inline]
44 pub fn load(&self, order: Ordering) -> *const T {
45 self.inner.load(order).cast_const()
46 }
47
48 #[inline]
50 pub fn store(&self, ptr: *const T, order: Ordering) {
51 self.inner.store(ptr.cast_mut(), order);
52 }
53
54 #[inline]
56 pub fn swap(&self, ptr: *const T, order: Ordering) -> *const T {
57 self.inner.swap(ptr.cast_mut(), order).cast_const()
58 }
59
60 #[inline]
65 pub fn compare_exchange(
66 &self,
67 current: *const T,
68 new: *const T,
69 success: Ordering,
70 failure: Ordering,
71 ) -> Result<*const T, *const T> {
72 self.inner
73 .compare_exchange(current.cast_mut(), new.cast_mut(), success, failure)
74 .map(|p| p.cast_const())
75 .map_err(|p| p.cast_const())
76 }
77
78 #[inline]
82 pub fn compare_exchange_weak(
83 &self,
84 current: *const T,
85 new: *const T,
86 success: Ordering,
87 failure: Ordering,
88 ) -> Result<*const T, *const T> {
89 self.inner
90 .compare_exchange_weak(current.cast_mut(), new.cast_mut(), success, failure)
91 .map(|p| p.cast_const())
92 .map_err(|p| p.cast_const())
93 }
94
95 #[inline]
99 pub fn try_update<F>(
100 &self,
101 set_order: Ordering,
102 fetch_order: Ordering,
103 mut f: F,
104 ) -> Result<*const T, *const T>
105 where
106 F: FnMut(*const T) -> Option<*const T>,
107 {
108 self.inner
109 .try_update(set_order, fetch_order, |p| f(p.cast_const()).map(|c| c.cast_mut()))
110 .map(|p| p.cast_const())
111 .map_err(|p| p.cast_const())
112 }
113
114 #[inline]
116 pub fn into_inner(self) -> *const T {
117 self.inner.into_inner().cast_const()
118 }
119}
120
121impl<T> core::fmt::Debug for AtomicConstPtr<T> {
122 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
123 f.debug_tuple("AtomicConstPtr").field(&self.load(Ordering::Relaxed)).finish()
124 }
125}
126
127impl<T> core::fmt::Pointer for AtomicConstPtr<T> {
128 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
129 core::fmt::Pointer::fmt(&self.load(Ordering::Relaxed), f)
130 }
131}
132
133impl<T> Default for AtomicConstPtr<T> {
134 #[inline]
135 fn default() -> Self {
136 Self::new(core::ptr::null())
137 }
138}
139
140impl<T> From<*const T> for AtomicConstPtr<T> {
141 #[inline]
142 fn from(ptr: *const T) -> Self {
143 Self::new(ptr)
144 }
145}
146
147#[inline]
157pub const unsafe fn slice_from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] {
158 if len == 0 {
159 &[]
160 } else {
161 unsafe { core::slice::from_raw_parts(data, len) }
163 }
164}
165
166#[inline]
177pub const unsafe fn slice_from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] {
178 if len == 0 {
179 &mut []
180 } else {
181 unsafe { core::slice::from_raw_parts_mut(data, len) }
183 }
184}
185
186#[cfg(test)]
187mod tests {
188 use super::*;
189
190 #[test]
191 fn test_slice_from_raw_parts_zero_length() {
192 let empty: &[u32] = unsafe { slice_from_raw_parts(core::ptr::null(), 0) };
193 assert!(empty.is_empty());
194
195 let empty_mut: &mut [u32] = unsafe { slice_from_raw_parts_mut(core::ptr::null_mut(), 0) };
196 assert!(empty_mut.is_empty());
197 }
198
199 #[test]
200 fn test_slice_from_raw_parts_non_empty() {
201 let mut arr = [10u32, 20, 30];
202 let s = unsafe { slice_from_raw_parts(arr.as_ptr(), arr.len()) };
203 assert_eq!(s, &[10, 20, 30]);
204
205 let s_mut = unsafe { slice_from_raw_parts_mut(arr.as_mut_ptr(), arr.len()) };
206 s_mut[1] = 25;
207 assert_eq!(arr, [10, 25, 30]);
208 }
209
210 #[test]
211 fn test_atomic_const_ptr_basic() {
212 static DUMMY: u32 = 42;
213 static DUMMY2: u32 = 99;
214
215 let ptr = AtomicConstPtr::new(&DUMMY as *const u32);
216 assert_eq!(ptr.load(Ordering::SeqCst), &DUMMY as *const u32);
217
218 ptr.store(&DUMMY2 as *const u32, Ordering::SeqCst);
219 assert_eq!(ptr.load(Ordering::SeqCst), &DUMMY2 as *const u32);
220
221 let old = ptr.swap(&DUMMY as *const u32, Ordering::SeqCst);
222 assert_eq!(old, &DUMMY2 as *const u32);
223 assert_eq!(ptr.load(Ordering::SeqCst), &DUMMY as *const u32);
224
225 let res = ptr.compare_exchange(
226 &DUMMY as *const u32,
227 &DUMMY2 as *const u32,
228 Ordering::SeqCst,
229 Ordering::SeqCst,
230 );
231 assert_eq!(res, Ok(&DUMMY as *const u32));
232 assert_eq!(ptr.load(Ordering::SeqCst), &DUMMY2 as *const u32);
233
234 let update_res = ptr.try_update(Ordering::SeqCst, Ordering::SeqCst, |p| {
235 if p == &DUMMY2 as *const u32 { Some(&DUMMY as *const u32) } else { None }
236 });
237 assert_eq!(update_res, Ok(&DUMMY2 as *const u32));
238 assert_eq!(ptr.load(Ordering::SeqCst), &DUMMY as *const u32);
239
240 let default_ptr: AtomicConstPtr<u32> = AtomicConstPtr::default();
241 assert!(default_ptr.load(Ordering::Relaxed).is_null());
242 }
243}