1#![allow(unused_macros)]
20#[allow(unused_imports)]
21use core::cell::UnsafeCell;
22use core::ops::{Deref, DerefMut};
23#[cfg(doc)]
24use core::sync::atomic;
25use core::sync::atomic::{AtomicBool, Ordering};
26
27#[cfg_attr(not(all(feature = "signal", unix)), path = "signal_none.rs")]
28mod signal;
29use signal::SignalGuard;
30
31struct Guard<'a, T> {
32 value: &'a mut T,
33 lock: &'a AtomicBool,
34 order: Ordering,
35 _signal: SignalGuard,
36}
37
38impl<'a, T> Deref for Guard<'a, T> {
39 type Target = T;
40
41 fn deref(&self) -> &T {
42 self.value
43 }
44}
45
46impl<'a, T> DerefMut for Guard<'a, T> {
47 fn deref_mut(&mut self) -> &mut T {
48 self.value
49 }
50}
51
52impl<'a, T> Drop for Guard<'a, T> {
53 fn drop(&mut self) {
54 self.lock.store(false, match self.order {
55 Ordering::SeqCst => Ordering::SeqCst,
56 _ => Ordering::Release,
57 });
58 }
59}
60
61#[allow(dead_code)]
62#[allow(unused_imports)]
63use Guard as _;
64
65macro_rules! define_fallback {
66 ($atomic:ident$(<$generic:ident>)?, $type:ty, $doc:expr) => {
67 pub struct $atomic$(<$generic>)? {
68 value: UnsafeCell<$type>,
69 lock: AtomicBool,
70 }
71
72 impl$(<$generic>)? $atomic$(<$generic>)? {
73 #[doc = concat!("\n\n", $doc, "::new`].")]
75 pub const fn new(v: $type) -> Self {
76 Self {
77 value: UnsafeCell::new(v),
78 lock: AtomicBool::new(false),
79 }
80 }
81
82 fn lock(&self, order: Ordering) -> Guard<'_, $type> {
83 let signal = SignalGuard::new();
84 while self
85 .lock
86 .compare_exchange_weak(
87 false,
88 true,
89 match order {
90 Ordering::SeqCst => Ordering::SeqCst,
91 _ => Ordering::Acquire,
92 },
93 Ordering::Relaxed,
94 )
95 .is_err()
96 {
97 while self.lock.load(Ordering::Relaxed) {
98 core::hint::spin_loop();
99 }
100 }
101 Guard {
102 value: unsafe { &mut *self.value.get() },
105 lock: &self.lock,
106 order,
107 _signal: signal,
108 }
109 }
110
111 #[doc = concat!("\n\n", $doc, "::get_mut`].")]
113 pub fn get_mut(&mut self) -> &mut $type {
114 self.value.get_mut()
115 }
116
117 #[doc = concat!("\n\n", $doc, "::into_inner`].")]
119 pub fn into_inner(self) -> $type {
120 self.value.into_inner()
121 }
122
123 #[doc = concat!("\n\n", $doc, "::load`].")]
125 pub fn load(&self, order: Ordering) -> $type {
126 *self.lock(order)
127 }
128
129 #[doc = concat!("\n\n", $doc, "::store`].")]
131 pub fn store(&self, val: $type, order: Ordering) {
132 let mut guard = self.lock(order);
133 *guard = val;
134 }
135
136 #[doc = concat!("\n\n", $doc, "::swap`].")]
139 pub fn swap(&self, val: $type, order: Ordering) -> $type {
140 let mut guard = self.lock(order);
141 core::mem::replace(&mut *guard, val)
142 }
143
144 #[doc = concat!("\n\n", $doc, "::compare_and_swap`].")]
147 pub fn compare_and_swap(
148 &self,
149 current: $type,
150 new: $type,
151 order: Ordering,
152 ) -> $type {
153 match self.compare_exchange(current, new, order, order) {
154 Ok(prev) => prev,
155 Err(prev) => prev,
156 }
157 }
158
159 #[doc = concat!("\n\n", $doc, "::compare_exchange`].")]
162 pub fn compare_exchange(
163 &self,
164 current: $type,
165 new: $type,
166 success: Ordering,
167 failure: Ordering,
168 ) -> Result<$type, $type> {
169 let mut guard = self.lock(success);
170 let prev = *guard;
171 if prev == current {
172 *guard = new;
173 Ok(prev)
174 } else {
175 guard.order = failure;
176 Err(prev)
177 }
178 }
179
180 #[doc = concat!("\n\n", $doc, "::compare_exchange_weak`].")]
183 pub fn compare_exchange_weak(
184 &self,
185 current: $type,
186 new: $type,
187 success: Ordering,
188 failure: Ordering,
189 ) -> Result<$type, $type> {
190 self.compare_exchange(current, new, success, failure)
191 }
192
193 #[doc = concat!("\n\n", $doc, "::fetch_update`].")]
196 pub fn fetch_update<F>(
197 &self,
198 set_order: Ordering,
199 fetch_order: Ordering,
200 mut f: F,
201 ) -> Result<$type, $type>
202 where
203 F: FnMut($type) -> Option<$type>,
204 {
205 let _ = fetch_order;
206 let mut guard = self.lock(set_order);
207 let prev = *guard;
208 if let Some(value) = f(prev) {
209 *guard = value;
210 Ok(prev)
211 } else {
212 Err(prev)
213 }
214 }
215
216 #[doc = concat!("\n\n", $doc, "::as_ptr`].")]
218 pub const fn as_ptr(&self) -> *mut $type {
219 self.value.get()
220 }
221 }
222
223 unsafe impl$(<$generic>)? Sync for $atomic$(<$generic>)? {}
225 };
226}
227
228macro_rules! define_fallback_int {
229 ($atomic:ident, $int:ty, $doc:expr) => {
230 define_fallback!($atomic, $int, $doc);
231
232 impl $atomic {
233 #[doc = concat!("\n\n", $doc, "::fetch_add`].")]
235 pub fn fetch_add(&self, val: $int, order: Ordering) -> $int {
236 let mut guard = self.lock(order);
237 let prev = *guard;
238 *guard += val;
239 prev
240 }
241
242 #[doc = concat!("\n\n", $doc, "::fetch_sub`].")]
244 pub fn fetch_sub(&self, val: $int, order: Ordering) -> $int {
245 let mut guard = self.lock(order);
246 let prev = *guard;
247 *guard -= val;
248 prev
249 }
250
251 #[doc = concat!("\n\n", $doc, "::fetch_and`].")]
253 pub fn fetch_and(&self, val: $int, order: Ordering) -> $int {
254 let mut guard = self.lock(order);
255 let prev = *guard;
256 *guard &= val;
257 prev
258 }
259
260 #[doc = concat!("\n\n", $doc, "::fetch_nand`].")]
262 pub fn fetch_nand(&self, val: $int, order: Ordering) -> $int {
263 let mut guard = self.lock(order);
264 let prev = *guard;
265 *guard = !(prev & val);
266 prev
267 }
268
269 #[doc = concat!("\n\n", $doc, "::fetch_or`].")]
271 pub fn fetch_or(&self, val: $int, order: Ordering) -> $int {
272 let mut guard = self.lock(order);
273 let prev = *guard;
274 *guard |= val;
275 prev
276 }
277
278 #[doc = concat!("\n\n", $doc, "::fetch_xor`].")]
280 pub fn fetch_xor(&self, val: $int, order: Ordering) -> $int {
281 let mut guard = self.lock(order);
282 let prev = *guard;
283 *guard ^= val;
284 prev
285 }
286
287 #[doc = concat!("\n\n", $doc, "::fetch_max`].")]
289 pub fn fetch_max(&self, val: $int, order: Ordering) -> $int {
290 let mut guard = self.lock(order);
291 let prev = *guard;
292 *guard = prev.max(val);
293 prev
294 }
295
296 #[doc = concat!("\n\n", $doc, "::fetch_min`].")]
298 pub fn fetch_min(&self, val: $int, order: Ordering) -> $int {
299 let mut guard = self.lock(order);
300 let prev = *guard;
301 *guard = prev.min(val);
302 prev
303 }
304 }
305 };
306}
307
308macro_rules! define_primitive_fallback {
309 ($atomic:ident, $int:ident, [$($cfg:tt)*], $($x:tt)*) => {
310 #[cfg(any(doc, feature = "force-fallback", not($($cfg)*)))]
311 define_fallback_int!(
312 $atomic,
313 $int,
314 concat!("See [`atomic::", stringify!($atomic))
315 );
316 };
317}
318
319#[cfg(feature = "primitives")]
320with_primitive_atomics!(define_primitive_fallback);
321
322#[cfg(feature = "primitives")]
323#[cfg(any(doc, feature = "force-fallback", not(target_has_atomic = "ptr")))]
324define_fallback!(AtomicPtr<T>, *mut T, "See [`atomic::AtomicPtr");
325
326macro_rules! define_c_fallback {
327 ($atomic:ident, $int:ident, $($x:tt)*) => {
328 define_fallback_int!(
329 $atomic,
330 super::c_types::$int,
331 "See, e.g., [`atomic::AtomicI32"
332 );
333 };
334}
335
336with_c_atomics!(define_c_fallback);
337
338#[cfg(doc)]
339define_fallback_int!(AtomicFallback, i32, "See, e.g., [`atomic::AtomicI32");
340
341#[cfg(doc)]
342define_fallback!(AtomicFallbackPtr<T>, *mut T, "See [`atomic::AtomicPtr");
343
344#[allow(dead_code)]
345fn allow_unused() {
346 let _ = SignalGuard::new;
347}