1use crate::sync::atomic::Atomic;
2#[cfg(test)]
3use crate::sync::ResourceSignature;
4use std::sync::atomic::Ordering;
5
6pub struct AtomicPtr<T> {
8 inner: Atomic<*mut T>,
9}
10
11impl<T> Default for AtomicPtr<T> {
12 fn default() -> Self {
13 Self::new(std::ptr::null_mut())
14 }
15}
16
17impl<T> From<*mut T> for AtomicPtr<T> {
18 fn from(p: *mut T) -> Self {
19 Self::new(p)
20 }
21}
22
23impl<T> std::fmt::Debug for AtomicPtr<T> {
24 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
25 std::fmt::Debug::fmt(unsafe { &self.raw_load() }, f)
26 }
27}
28
29impl<T> std::fmt::Pointer for AtomicPtr<T> {
30 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
31 std::fmt::Pointer::fmt(unsafe { &self.raw_load() }, f)
32 }
33}
34
35unsafe impl<T> Send for AtomicPtr<T> {}
38unsafe impl<T> Sync for AtomicPtr<T> {}
39
40impl<T> AtomicPtr<T> {
41 #[track_caller]
43 pub const fn new(v: *mut T) -> Self {
44 Self { inner: Atomic::new(v) }
45 }
46
47 pub fn get_mut(&mut self) -> &mut *mut T {
49 self.inner.get_mut()
50 }
51
52 pub fn into_inner(self) -> *mut T {
54 self.inner.into_inner()
55 }
56
57 pub fn load(&self, order: Ordering) -> *mut T {
59 self.inner.load(order)
60 }
61
62 pub fn store(&self, val: *mut T, order: Ordering) {
64 self.inner.store(val, order)
65 }
66
67 pub fn swap(&self, val: *mut T, order: Ordering) -> *mut T {
69 self.inner.swap(val, order)
70 }
71
72 pub fn try_update(
76 &self,
77 set_order: Ordering,
78 fetch_order: Ordering,
79 mut f: impl FnMut(*mut T) -> Option<*mut T>,
80 ) -> Result<*mut T, *mut T> {
81 let mut prev = self.load(fetch_order);
82 while let Some(next) = f(prev) {
83 match self.compare_exchange_weak(prev, next, set_order, fetch_order) {
84 x @ Ok(_) => return x,
85 Err(next_prev) => prev = next_prev,
86 }
87 }
88 Err(prev)
89 }
90
91 pub fn fetch_update<F>(&self, set_order: Ordering, fetch_order: Ordering, f: F) -> Result<*mut T, *mut T>
96 where
97 F: FnMut(*mut T) -> Option<*mut T>,
98 {
99 self.try_update(set_order, fetch_order, f)
100 }
101
102 pub fn update(&self, set_order: Ordering, fetch_order: Ordering, mut f: impl FnMut(*mut T) -> *mut T) -> *mut T {
105 let mut prev = self.load(fetch_order);
106 loop {
107 match self.compare_exchange_weak(prev, f(prev), set_order, fetch_order) {
108 Ok(x) => break x,
109 Err(next_prev) => prev = next_prev,
110 }
111 }
112 }
113
114 #[deprecated(since = "0.0.6", note = "Use `compare_exchange` or `compare_exchange_weak` instead")]
117 pub fn compare_and_swap(&self, current: *mut T, new: *mut T, order: Ordering) -> *mut T {
118 match self.compare_exchange(current, new, order, order) {
119 Ok(v) => v,
120 Err(v) => v,
121 }
122 }
123
124 pub fn compare_exchange(
131 &self,
132 current: *mut T,
133 new: *mut T,
134 success: Ordering,
135 failure: Ordering,
136 ) -> Result<*mut T, *mut T> {
137 self.inner
138 .try_update(success, failure, |val| (val == current).then_some(new))
139 }
140
141 pub fn compare_exchange_weak(
150 &self,
151 current: *mut T,
152 new: *mut T,
153 success: Ordering,
154 failure: Ordering,
155 ) -> Result<*mut T, *mut T> {
156 self.compare_exchange(current, new, success, failure)
157 }
158
159 pub fn fetch_ptr_add(&self, val: usize, order: Ordering) -> *mut T {
164 self.fetch_byte_add(val.wrapping_mul(std::mem::size_of::<T>()), order)
165 }
166
167 pub fn fetch_ptr_sub(&self, val: usize, order: Ordering) -> *mut T {
172 self.fetch_byte_sub(val.wrapping_mul(std::mem::size_of::<T>()), order)
173 }
174
175 pub fn fetch_byte_add(&self, val: usize, order: Ordering) -> *mut T {
179 self.inner
180 .try_update(order, order, |old| Some(old.wrapping_byte_add(val)))
181 .unwrap()
182 }
183
184 pub fn fetch_byte_sub(&self, val: usize, order: Ordering) -> *mut T {
188 self.inner
189 .try_update(order, order, |old| Some(old.wrapping_byte_sub(val)))
190 .unwrap()
191 }
192
193 pub fn fetch_or(&self, val: usize, order: Ordering) -> *mut T {
196 self.inner
197 .try_update(order, order, |old| Some(old.map_addr(|addr| addr | val)))
198 .unwrap()
199 }
200
201 pub fn fetch_and(&self, val: usize, order: Ordering) -> *mut T {
204 self.inner
205 .try_update(order, order, |old| Some(old.map_addr(|addr| addr & val)))
206 .unwrap()
207 }
208
209 pub fn fetch_xor(&self, val: usize, order: Ordering) -> *mut T {
212 self.inner
213 .try_update(order, order, |old| Some(old.map_addr(|addr| addr ^ val)))
214 .unwrap()
215 }
216
217 pub unsafe fn raw_load(&self) -> *mut T {
225 self.inner.raw_load()
226 }
227
228 #[cfg(test)]
229 pub(crate) fn signature(&self) -> ResourceSignature {
230 self.inner.signature()
231 }
232}