qubit_atomic/atomic/atomic.rs
1/*******************************************************************************
2 *
3 * Copyright (c) 2025 - 2026 Haixing Hu.
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0.
8 *
9 ******************************************************************************/
10
11//! # Generic Atomic Wrapper
12//!
13//! Provides the public [`Atomic<T>`] wrapper for supported primitive values.
14//!
15
16use std::{
17 fmt,
18 sync::atomic::Ordering,
19};
20
21use super::atomic_integer_value::AtomicIntegerValue;
22use super::atomic_number_ops::AtomicNumberOps;
23use super::atomic_ops::AtomicOps;
24use super::atomic_value::AtomicValue;
25
26/// A high-level atomic wrapper for supported primitive value types.
27///
28/// This type is the main entry point for primitive atomic values. It hides
29/// explicit memory-ordering parameters behind crate-defined defaults while
30/// still exposing the raw backend through [`inner`](Self::inner) for advanced
31/// use cases.
32///
33/// Supported value types are:
34///
35/// - `bool`
36/// - `u8`, `i8`, `u16`, `i16`, `u32`, `i32`, `u64`, `i64`, `u128`, `i128`
37/// - `usize`, `isize`
38/// - `f32`, `f64`
39///
40/// The `i128` and `u128` specializations use `portable-atomic` internally
41/// because the corresponding standard-library atomic types are not yet stable.
42///
43/// # Specialization API
44///
45/// Rustdoc documents [`Atomic<T>`] as one generic type rather than generating a
46/// separate page for each concrete `T`. The following table summarizes the
47/// methods available for each specialization:
48///
49/// | Specialization | Additional methods |
50/// | --- | --- |
51/// | `Atomic<bool>` | `fetch_set`, `fetch_clear`, `fetch_not`, `fetch_and`, `fetch_or`, `fetch_xor`, `set_if_false`, `set_if_true` |
52/// | `Atomic<i8>`, `Atomic<i16>`, `Atomic<i32>`, `Atomic<i64>`, `Atomic<i128>`, `Atomic<isize>` | `fetch_add`, `fetch_sub`, `fetch_mul`, `fetch_div`, `fetch_inc`, `fetch_dec`, `fetch_*_with_ordering`, `fetch_and`, `fetch_or`, `fetch_xor`, `fetch_not`, `fetch_accumulate`, `fetch_max`, `fetch_min` |
53/// | `Atomic<u8>`, `Atomic<u16>`, `Atomic<u32>`, `Atomic<u64>`, `Atomic<u128>`, `Atomic<usize>` | `fetch_add`, `fetch_sub`, `fetch_mul`, `fetch_div`, `fetch_inc`, `fetch_dec`, `fetch_*_with_ordering`, `fetch_and`, `fetch_or`, `fetch_xor`, `fetch_not`, `fetch_accumulate`, `fetch_max`, `fetch_min` |
54/// | `Atomic<f32>`, `Atomic<f64>` | `fetch_add`, `fetch_sub`, `fetch_mul`, `fetch_div` |
55///
56/// All supported specializations also provide [`new`](Self::new),
57/// [`load`](Self::load), [`store`](Self::store), [`swap`](Self::swap),
58/// [`compare_set`](Self::compare_set),
59/// [`compare_set_weak`](Self::compare_set_weak),
60/// [`compare_and_exchange`](Self::compare_and_exchange),
61/// [`compare_and_exchange_weak`](Self::compare_and_exchange_weak),
62/// [`fetch_update`](Self::fetch_update), [`try_update`](Self::try_update),
63/// and [`inner`](Self::inner).
64///
65/// Integer arithmetic operations intentionally follow Rust atomic integer
66/// semantics and wrap on overflow and underflow. Use [`crate::AtomicCount`] or
67/// [`crate::AtomicSignedCount`] when overflow or underflow must be rejected
68/// instead of wrapping.
69///
70/// Floating-point compare-and-set/exchange operations compare raw
71/// [`to_bits`](f32::to_bits) representations, not [`PartialEq`]. This means
72/// distinct bit patterns that compare equal, such as `0.0` and `-0.0`, do not
73/// match for CAS, and NaN payloads must match exactly. Prefer
74/// [`compare_set`](Self::compare_set) or [`compare_set_weak`](Self::compare_set_weak)
75/// when the caller needs an explicit success indicator for `f32` or `f64`.
76///
77/// # Example
78///
79/// ```rust
80/// use qubit_atomic::Atomic;
81///
82/// let counter = Atomic::new(0);
83/// counter.fetch_inc();
84/// assert_eq!(counter.load(), 1);
85///
86/// let flag = Atomic::new(false);
87/// assert_eq!(flag.fetch_set(), false);
88/// assert!(flag.load());
89/// ```
90///
91/// When the value type is ambiguous (for example integer literals), specify
92/// `T` explicitly with a [turbofish] on the constructor, or by annotating the
93/// binding:
94///
95/// ```rust
96/// use qubit_atomic::Atomic;
97///
98/// let wide: Atomic<u64> = Atomic::new(0);
99/// assert_eq!(wide.load(), 0u64);
100///
101/// let narrow = Atomic::<i16>::new(0);
102/// assert_eq!(narrow.load(), 0i16);
103/// ```
104///
105/// [turbofish]: https://doc.rust-lang.org/book/appendix-02-operators.html#the-turbofish
106///
107#[doc(alias = "AtomicBool")]
108#[doc(alias = "AtomicI8")]
109#[doc(alias = "AtomicU8")]
110#[doc(alias = "AtomicI16")]
111#[doc(alias = "AtomicU16")]
112#[doc(alias = "AtomicI32")]
113#[doc(alias = "AtomicU32")]
114#[doc(alias = "AtomicI64")]
115#[doc(alias = "AtomicU64")]
116#[doc(alias = "AtomicI128")]
117#[doc(alias = "AtomicU128")]
118#[doc(alias = "AtomicIsize")]
119#[doc(alias = "AtomicUsize")]
120#[doc(alias = "AtomicF32")]
121#[doc(alias = "AtomicF64")]
122#[repr(transparent)]
123pub struct Atomic<T>
124where
125 T: AtomicValue,
126{
127 /// Primitive backend that performs the concrete atomic operations for `T`.
128 primitive: T::Primitive,
129}
130
131impl<T> Atomic<T>
132where
133 T: AtomicValue,
134{
135 /// Creates a new atomic value.
136 ///
137 /// # Parameters
138 ///
139 /// * `value` - The initial value.
140 ///
141 /// # Returns
142 ///
143 /// An atomic wrapper initialized to `value`.
144 ///
145 /// # Example
146 ///
147 /// ```rust
148 /// use qubit_atomic::Atomic;
149 ///
150 /// let atomic = Atomic::new(42);
151 /// assert_eq!(atomic.load(), 42);
152 /// ```
153 ///
154 /// To pick a concrete `T` when inference would be ambiguous (for example
155 /// `0` as `u64` vs `i32`), write `Atomic::<T>::new(...)` (turbofish) or add
156 /// a type annotation on the binding (for example `let x: Atomic<u64> = ...`):
157 ///
158 /// ```rust
159 /// use qubit_atomic::Atomic;
160 ///
161 /// let a = Atomic::<u64>::new(0);
162 /// assert_eq!(a.load(), 0u64);
163 ///
164 /// let b: Atomic<isize> = Atomic::new(0);
165 /// assert_eq!(b.load(), 0isize);
166 /// ```
167 #[inline]
168 pub fn new(value: T) -> Self {
169 Self {
170 primitive: T::new_primitive(value),
171 }
172 }
173
174 /// Loads the current value.
175 ///
176 /// Uses `Acquire` ordering by default.
177 ///
178 /// # Returns
179 ///
180 /// The current value.
181 ///
182 /// # Example
183 ///
184 /// ```rust
185 /// use qubit_atomic::Atomic;
186 ///
187 /// let atomic = Atomic::new(7);
188 /// assert_eq!(atomic.load(), 7);
189 /// ```
190 #[inline]
191 pub fn load(&self) -> T {
192 AtomicOps::load(&self.primitive)
193 }
194
195 /// Stores a new value.
196 ///
197 /// Uses `Release` ordering by default.
198 ///
199 /// # Parameters
200 ///
201 /// * `value` - The new value to store.
202 ///
203 /// # Example
204 ///
205 /// ```rust
206 /// use qubit_atomic::Atomic;
207 ///
208 /// let atomic = Atomic::new(1);
209 /// atomic.store(2);
210 /// assert_eq!(atomic.load(), 2);
211 /// ```
212 #[inline]
213 pub fn store(&self, value: T) {
214 AtomicOps::store(&self.primitive, value);
215 }
216
217 /// Swaps the current value with `value`.
218 ///
219 /// Unlike [`store`](Self::store), this returns the value that was in the
220 /// atomic immediately before the swap, in the same atomic step. Use
221 /// [`store`](Self::store) when you do not need the previous value.
222 ///
223 /// Uses `AcqRel` ordering by default.
224 ///
225 /// # Parameters
226 ///
227 /// * `value` - The new value to store.
228 ///
229 /// # Returns
230 ///
231 /// The previous value.
232 ///
233 /// # Example
234 ///
235 /// ```rust
236 /// use qubit_atomic::Atomic;
237 ///
238 /// let a = Atomic::new(100);
239 /// a.store(200);
240 /// // store has no return value; you only see the new value via load().
241 /// assert_eq!(a.load(), 200);
242 ///
243 /// let b = Atomic::new(100);
244 /// // swap returns the old value and installs the new one atomically.
245 /// assert_eq!(b.swap(200), 100);
246 /// assert_eq!(b.load(), 200);
247 /// ```
248 #[inline]
249 pub fn swap(&self, value: T) -> T {
250 AtomicOps::swap(&self.primitive, value)
251 }
252
253 /// Compares the current value with `current` and stores `new` on match.
254 ///
255 /// Uses `AcqRel` ordering on success and `Acquire` ordering on failure.
256 ///
257 /// # Parameters
258 ///
259 /// * `current` - The expected current value.
260 /// * `new` - The replacement value to store when the comparison matches.
261 ///
262 /// # Returns
263 ///
264 /// `Ok(())` when the value was replaced.
265 ///
266 /// # Errors
267 ///
268 /// Returns `Err(actual)` with the observed value when the comparison
269 /// fails. In that case, `new` is not stored.
270 ///
271 /// # Example
272 ///
273 /// ```rust
274 /// use qubit_atomic::Atomic;
275 ///
276 /// let atomic = Atomic::new(1);
277 /// assert!(atomic.compare_set(1, 2).is_ok());
278 /// assert_eq!(atomic.load(), 2);
279 /// assert_eq!(atomic.compare_set(1, 3), Err(2));
280 /// ```
281 #[inline]
282 pub fn compare_set(&self, current: T, new: T) -> Result<(), T> {
283 AtomicOps::compare_set(&self.primitive, current, new)
284 }
285
286 /// Weak version of [`compare_set`](Self::compare_set).
287 ///
288 /// This operation may fail spuriously and is intended for retry loops.
289 ///
290 /// # Parameters
291 ///
292 /// * `current` - The expected current value.
293 /// * `new` - The replacement value to store when the comparison matches.
294 ///
295 /// # Returns
296 ///
297 /// `Ok(())` when the value was replaced.
298 ///
299 /// # Errors
300 ///
301 /// Returns `Err(actual)` with the observed value when the comparison
302 /// fails, including possible spurious failures. In that case, `new` is not
303 /// stored.
304 ///
305 /// # Example
306 ///
307 /// ```rust
308 /// use qubit_atomic::Atomic;
309 ///
310 /// let atomic = Atomic::new(1);
311 /// loop {
312 /// match atomic.compare_set_weak(1, 2) {
313 /// Ok(()) => break,
314 /// Err(actual) => assert_eq!(actual, 1),
315 /// }
316 /// }
317 /// assert_eq!(atomic.load(), 2);
318 /// ```
319 #[inline]
320 pub fn compare_set_weak(&self, current: T, new: T) -> Result<(), T> {
321 AtomicOps::compare_set_weak(&self.primitive, current, new)
322 }
323
324 /// Compares and exchanges the value, returning the value seen before the
325 /// operation.
326 ///
327 /// If the return value equals `current`, the exchange succeeded.
328 ///
329 /// # Parameters
330 ///
331 /// * `current` - The expected current value.
332 /// * `new` - The replacement value to store when the comparison matches.
333 ///
334 /// # Returns
335 ///
336 /// The value observed before the operation completed. If the returned
337 /// value equals `current`, the exchange succeeded; otherwise it is the
338 /// actual value that prevented the exchange.
339 ///
340 /// For `Atomic<f32>` and `Atomic<f64>`, CAS compares raw IEEE-754 bit
341 /// patterns rather than [`PartialEq`]. A returned floating-point value
342 /// comparing equal to `current` is therefore not always enough to prove
343 /// success; use [`compare_set`](Self::compare_set) for an explicit
344 /// `Ok`/`Err`, or compare [`to_bits`](f32::to_bits) values yourself.
345 ///
346 /// # Example
347 ///
348 /// ```rust
349 /// use qubit_atomic::Atomic;
350 ///
351 /// let atomic = Atomic::new(5);
352 /// assert_eq!(atomic.compare_and_exchange(5, 10), 5);
353 /// assert_eq!(atomic.load(), 10);
354 /// assert_eq!(atomic.compare_and_exchange(5, 0), 10);
355 /// ```
356 #[inline]
357 pub fn compare_and_exchange(&self, current: T, new: T) -> T {
358 AtomicOps::compare_exchange(&self.primitive, current, new)
359 }
360
361 /// Weak version of [`compare_and_exchange`](Self::compare_and_exchange).
362 ///
363 /// This operation may fail spuriously and is intended for retry loops.
364 ///
365 /// # Parameters
366 ///
367 /// * `current` - The expected current value.
368 /// * `new` - The replacement value to store when the comparison matches.
369 ///
370 /// # Returns
371 ///
372 /// The value observed before the operation completed. Because this
373 /// operation may fail spuriously, a returned value equal to `current` does
374 /// not by itself prove that `new` was stored; use
375 /// [`compare_set_weak`](Self::compare_set_weak) when the caller needs an
376 /// explicit success indicator.
377 ///
378 /// For `Atomic<f32>` and `Atomic<f64>`, the same caveat applies to raw-bit
379 /// equality: `0.0` and `-0.0` compare equal by [`PartialEq`] but are
380 /// different CAS values. Use [`compare_set_weak`](Self::compare_set_weak)
381 /// or compare [`to_bits`](f32::to_bits) values when distinguishing success
382 /// from failure matters.
383 ///
384 /// # Example
385 ///
386 /// Weak CAS may fail spuriously; retry until [`load`](Self::load) shows the
387 /// expected outcome (or use [`compare_set_weak`](Self::compare_set_weak)
388 /// which reports success explicitly).
389 ///
390 /// ```rust
391 /// use qubit_atomic::Atomic;
392 ///
393 /// let atomic = Atomic::new(5);
394 /// loop {
395 /// let _ = atomic.compare_and_exchange_weak(5, 10);
396 /// if atomic.load() == 10 {
397 /// break;
398 /// }
399 /// }
400 /// ```
401 #[inline]
402 pub fn compare_and_exchange_weak(&self, current: T, new: T) -> T {
403 AtomicOps::compare_exchange_weak(&self.primitive, current, new)
404 }
405
406 /// Updates the value with a function and returns the previous value.
407 ///
408 /// The update uses a CAS loop until it succeeds. The closure may be called
409 /// more than once under contention.
410 ///
411 /// # Parameters
412 ///
413 /// * `f` - A function that maps the current value to the next value.
414 ///
415 /// # Returns
416 ///
417 /// The value before the successful update.
418 ///
419 /// # Example
420 ///
421 /// ```rust
422 /// use qubit_atomic::Atomic;
423 ///
424 /// let atomic = Atomic::new(3);
425 /// assert_eq!(atomic.fetch_update(|x| x * 2), 3);
426 /// assert_eq!(atomic.load(), 6);
427 /// ```
428 #[inline]
429 pub fn fetch_update<F>(&self, f: F) -> T
430 where
431 F: Fn(T) -> T,
432 {
433 AtomicOps::fetch_update(&self.primitive, f)
434 }
435
436 /// Conditionally updates the value with a function.
437 ///
438 /// The update uses a CAS loop until it succeeds or the closure rejects the
439 /// observed current value by returning `None`. The closure may be called
440 /// more than once under contention.
441 ///
442 /// # Parameters
443 ///
444 /// * `f` - A function that maps the current value to `Some(next)` to update
445 /// the atomic, or `None` to leave it unchanged.
446 ///
447 /// # Returns
448 ///
449 /// `Some(old_value)` with the value before the successful update, or `None`
450 /// when `f` rejects the observed current value.
451 ///
452 /// # Example
453 ///
454 /// ```rust
455 /// use qubit_atomic::Atomic;
456 ///
457 /// let atomic = Atomic::new(3);
458 /// assert_eq!(atomic.try_update(|x| (x % 2 == 1).then_some(x + 1)), Some(3));
459 /// assert_eq!(atomic.load(), 4);
460 /// assert_eq!(atomic.try_update(|x| (x % 2 == 1).then_some(x + 1)), None);
461 /// assert_eq!(atomic.load(), 4);
462 /// ```
463 #[inline]
464 pub fn try_update<F>(&self, f: F) -> Option<T>
465 where
466 F: Fn(T) -> Option<T>,
467 {
468 AtomicOps::try_update(&self.primitive, f)
469 }
470
471 /// Returns the raw backend atomic value.
472 ///
473 /// Use this method only when the default orderings are not appropriate
474 /// and the caller needs direct access to the backend atomic storage.
475 ///
476 /// # Returns
477 ///
478 /// A shared reference to the raw backend atomic value.
479 ///
480 /// # Example
481 ///
482 /// ```rust
483 /// use qubit_atomic::Atomic;
484 /// use std::sync::atomic::Ordering;
485 ///
486 /// let atomic = Atomic::<i32>::new(0);
487 /// assert_eq!(atomic.inner().load(Ordering::Relaxed), 0);
488 /// ```
489 #[inline]
490 pub fn inner(&self) -> &T::Inner {
491 T::inner(&self.primitive)
492 }
493}
494
495impl<T> Atomic<T>
496where
497 T: AtomicValue,
498 T::Primitive: AtomicNumberOps<Value = T>,
499{
500 /// Adds `delta` to the value and returns the previous value.
501 ///
502 /// Integer atomics use relaxed ordering for this operation. Floating-point
503 /// atomics use a CAS loop. Integer addition wraps on overflow and
504 /// underflow.
505 ///
506 /// # Parameters
507 ///
508 /// * `delta` - The value to add.
509 ///
510 /// # Returns
511 ///
512 /// The value before the addition.
513 ///
514 /// # Example
515 ///
516 /// ```rust
517 /// use qubit_atomic::Atomic;
518 ///
519 /// let atomic = Atomic::new(10);
520 /// assert_eq!(atomic.fetch_add(3), 10);
521 /// assert_eq!(atomic.load(), 13);
522 /// ```
523 #[inline]
524 pub fn fetch_add(&self, delta: T) -> T {
525 AtomicNumberOps::fetch_add(&self.primitive, delta)
526 }
527
528 /// Subtracts `delta` from the value and returns the previous value.
529 ///
530 /// Integer atomics use relaxed ordering for this operation. Floating-point
531 /// atomics use a CAS loop. Integer subtraction wraps on overflow and
532 /// underflow.
533 ///
534 /// # Parameters
535 ///
536 /// * `delta` - The value to subtract.
537 ///
538 /// # Returns
539 ///
540 /// The value before the subtraction.
541 ///
542 /// # Example
543 ///
544 /// ```rust
545 /// use qubit_atomic::Atomic;
546 ///
547 /// let atomic = Atomic::new(10);
548 /// assert_eq!(atomic.fetch_sub(3), 10);
549 /// assert_eq!(atomic.load(), 7);
550 /// ```
551 #[inline]
552 pub fn fetch_sub(&self, delta: T) -> T {
553 AtomicNumberOps::fetch_sub(&self.primitive, delta)
554 }
555
556 /// Multiplies the value by `factor` and returns the previous value.
557 ///
558 /// This operation uses a CAS loop. Integer multiplication wraps on
559 /// overflow and underflow.
560 ///
561 /// # Parameters
562 ///
563 /// * `factor` - The value to multiply by.
564 ///
565 /// # Returns
566 ///
567 /// The value before the multiplication.
568 ///
569 /// # Example
570 ///
571 /// ```rust
572 /// use qubit_atomic::Atomic;
573 ///
574 /// let atomic = Atomic::new(3);
575 /// assert_eq!(atomic.fetch_mul(4), 3);
576 /// assert_eq!(atomic.load(), 12);
577 /// ```
578 #[inline]
579 pub fn fetch_mul(&self, factor: T) -> T {
580 AtomicNumberOps::fetch_mul(&self.primitive, factor)
581 }
582
583 /// Divides the value by `divisor` and returns the previous value.
584 ///
585 /// This operation uses a CAS loop. Integer division uses wrapping
586 /// semantics; for signed integers, `MIN / -1` wraps to `MIN`.
587 ///
588 /// # Parameters
589 ///
590 /// * `divisor` - The value to divide by.
591 ///
592 /// # Returns
593 ///
594 /// The value before the division.
595 ///
596 /// # Panics
597 ///
598 /// For integer specializations, panics if `divisor` is zero. Floating-point
599 /// specializations follow IEEE-754 division semantics and do not panic
600 /// solely because `divisor` is zero.
601 ///
602 /// # Example
603 ///
604 /// ```rust
605 /// use qubit_atomic::Atomic;
606 ///
607 /// let atomic = Atomic::new(20);
608 /// assert_eq!(atomic.fetch_div(4), 20);
609 /// assert_eq!(atomic.load(), 5);
610 /// ```
611 #[inline]
612 pub fn fetch_div(&self, divisor: T) -> T {
613 AtomicNumberOps::fetch_div(&self.primitive, divisor)
614 }
615}
616
617impl<T> Atomic<T>
618where
619 T: AtomicIntegerValue,
620{
621 /// Increments the value by one and returns the previous value.
622 ///
623 /// # Returns
624 ///
625 /// The value before the increment.
626 ///
627 /// # Example
628 ///
629 /// ```rust
630 /// use qubit_atomic::Atomic;
631 ///
632 /// let atomic = Atomic::new(0);
633 /// assert_eq!(atomic.fetch_inc(), 0);
634 /// assert_eq!(atomic.load(), 1);
635 /// ```
636 #[inline]
637 pub fn fetch_inc(&self) -> T {
638 T::fetch_inc(&self.primitive)
639 }
640
641 /// Increments the value by one with an explicit memory ordering and returns
642 /// the previous value.
643 ///
644 /// Arithmetic wraps on overflow, matching Rust atomic integer operations.
645 ///
646 /// # Parameters
647 ///
648 /// * `ordering` - The memory ordering used by the atomic read-modify-write
649 /// operation.
650 ///
651 /// # Returns
652 ///
653 /// The value before the increment.
654 ///
655 /// # Example
656 ///
657 /// ```rust
658 /// use qubit_atomic::Atomic;
659 /// use std::sync::atomic::Ordering;
660 ///
661 /// let atomic = Atomic::new(0);
662 /// assert_eq!(atomic.fetch_inc_with_ordering(Ordering::AcqRel), 0);
663 /// assert_eq!(atomic.load(), 1);
664 /// ```
665 #[inline]
666 pub fn fetch_inc_with_ordering(&self, ordering: Ordering) -> T {
667 T::fetch_inc_with_ordering(&self.primitive, ordering)
668 }
669
670 /// Decrements the value by one and returns the previous value.
671 ///
672 /// # Returns
673 ///
674 /// The value before the decrement.
675 ///
676 /// # Example
677 ///
678 /// ```rust
679 /// use qubit_atomic::Atomic;
680 ///
681 /// let atomic = Atomic::new(1);
682 /// assert_eq!(atomic.fetch_dec(), 1);
683 /// assert_eq!(atomic.load(), 0);
684 /// ```
685 #[inline]
686 pub fn fetch_dec(&self) -> T {
687 T::fetch_dec(&self.primitive)
688 }
689
690 /// Decrements the value by one with an explicit memory ordering and returns
691 /// the previous value.
692 ///
693 /// Arithmetic wraps on underflow, matching Rust atomic integer operations.
694 ///
695 /// # Parameters
696 ///
697 /// * `ordering` - The memory ordering used by the atomic read-modify-write
698 /// operation.
699 ///
700 /// # Returns
701 ///
702 /// The value before the decrement.
703 ///
704 /// # Example
705 ///
706 /// ```rust
707 /// use qubit_atomic::Atomic;
708 /// use std::sync::atomic::Ordering;
709 ///
710 /// let atomic = Atomic::new(1);
711 /// assert_eq!(atomic.fetch_dec_with_ordering(Ordering::AcqRel), 1);
712 /// assert_eq!(atomic.load(), 0);
713 /// ```
714 #[inline]
715 pub fn fetch_dec_with_ordering(&self, ordering: Ordering) -> T {
716 T::fetch_dec_with_ordering(&self.primitive, ordering)
717 }
718
719 /// Adds `delta` with an explicit memory ordering and returns the previous
720 /// value.
721 ///
722 /// Arithmetic wraps on overflow and underflow, matching Rust atomic integer
723 /// operations.
724 ///
725 /// # Parameters
726 ///
727 /// * `delta` - The value to add.
728 /// * `ordering` - The memory ordering used by the atomic read-modify-write
729 /// operation.
730 ///
731 /// # Returns
732 ///
733 /// The value before the addition.
734 ///
735 /// # Example
736 ///
737 /// ```rust
738 /// use qubit_atomic::Atomic;
739 /// use std::sync::atomic::Ordering;
740 ///
741 /// let atomic = Atomic::new(10);
742 /// assert_eq!(atomic.fetch_add_with_ordering(5, Ordering::AcqRel), 10);
743 /// assert_eq!(atomic.load(), 15);
744 /// ```
745 #[inline]
746 pub fn fetch_add_with_ordering(&self, delta: T, ordering: Ordering) -> T {
747 T::fetch_add_with_ordering(&self.primitive, delta, ordering)
748 }
749
750 /// Subtracts `delta` with an explicit memory ordering and returns the
751 /// previous value.
752 ///
753 /// Arithmetic wraps on overflow and underflow, matching Rust atomic integer
754 /// operations.
755 ///
756 /// # Parameters
757 ///
758 /// * `delta` - The value to subtract.
759 /// * `ordering` - The memory ordering used by the atomic read-modify-write
760 /// operation.
761 ///
762 /// # Returns
763 ///
764 /// The value before the subtraction.
765 ///
766 /// # Example
767 ///
768 /// ```rust
769 /// use qubit_atomic::Atomic;
770 /// use std::sync::atomic::Ordering;
771 ///
772 /// let atomic = Atomic::new(10);
773 /// assert_eq!(atomic.fetch_sub_with_ordering(3, Ordering::AcqRel), 10);
774 /// assert_eq!(atomic.load(), 7);
775 /// ```
776 #[inline]
777 pub fn fetch_sub_with_ordering(&self, delta: T, ordering: Ordering) -> T {
778 T::fetch_sub_with_ordering(&self.primitive, delta, ordering)
779 }
780
781 /// Applies bitwise AND and returns the previous value.
782 ///
783 /// # Parameters
784 ///
785 /// * `value` - The mask to apply.
786 ///
787 /// # Returns
788 ///
789 /// The value before the operation.
790 ///
791 /// # Example
792 ///
793 /// ```rust
794 /// use qubit_atomic::Atomic;
795 ///
796 /// let atomic = Atomic::<u8>::new(0b1111);
797 /// assert_eq!(atomic.fetch_and(0b1010), 0b1111);
798 /// assert_eq!(atomic.load(), 0b1010);
799 /// ```
800 #[inline]
801 pub fn fetch_and(&self, value: T) -> T {
802 T::fetch_and(&self.primitive, value)
803 }
804
805 /// Applies bitwise OR and returns the previous value.
806 ///
807 /// # Parameters
808 ///
809 /// * `value` - The mask to apply.
810 ///
811 /// # Returns
812 ///
813 /// The value before the operation.
814 ///
815 /// # Example
816 ///
817 /// ```rust
818 /// use qubit_atomic::Atomic;
819 ///
820 /// let atomic = Atomic::<u8>::new(0b1000);
821 /// assert_eq!(atomic.fetch_or(0b0011), 0b1000);
822 /// assert_eq!(atomic.load(), 0b1011);
823 /// ```
824 #[inline]
825 pub fn fetch_or(&self, value: T) -> T {
826 T::fetch_or(&self.primitive, value)
827 }
828
829 /// Applies bitwise XOR and returns the previous value.
830 ///
831 /// # Parameters
832 ///
833 /// * `value` - The mask to apply.
834 ///
835 /// # Returns
836 ///
837 /// The value before the operation.
838 ///
839 /// # Example
840 ///
841 /// ```rust
842 /// use qubit_atomic::Atomic;
843 ///
844 /// let atomic = Atomic::<u8>::new(0b1111);
845 /// assert_eq!(atomic.fetch_xor(0b1010), 0b1111);
846 /// assert_eq!(atomic.load(), 0b0101);
847 /// ```
848 #[inline]
849 pub fn fetch_xor(&self, value: T) -> T {
850 T::fetch_xor(&self.primitive, value)
851 }
852
853 /// Flips all bits and returns the previous value.
854 ///
855 /// # Returns
856 ///
857 /// The value before the operation.
858 ///
859 /// # Example
860 ///
861 /// ```rust
862 /// use qubit_atomic::Atomic;
863 ///
864 /// let atomic = Atomic::<i32>::new(0);
865 /// assert_eq!(atomic.fetch_not(), 0);
866 /// assert_eq!(atomic.load(), !0);
867 /// ```
868 #[inline]
869 pub fn fetch_not(&self) -> T {
870 T::fetch_not(&self.primitive)
871 }
872
873 /// Updates the value by accumulating it with `value`.
874 ///
875 /// # Parameters
876 ///
877 /// * `value` - The right-hand input to the accumulator.
878 /// * `f` - A function that combines the current value and `value`.
879 ///
880 /// # Returns
881 ///
882 /// The value before the successful update.
883 ///
884 /// The closure may be called more than once when concurrent updates cause
885 /// CAS retries.
886 ///
887 /// # Example
888 ///
889 /// ```rust
890 /// use qubit_atomic::Atomic;
891 ///
892 /// let atomic = Atomic::new(10);
893 /// assert_eq!(atomic.fetch_accumulate(5, |a, b| a + b), 10);
894 /// assert_eq!(atomic.load(), 15);
895 /// ```
896 #[inline]
897 pub fn fetch_accumulate<F>(&self, value: T, f: F) -> T
898 where
899 F: Fn(T, T) -> T,
900 {
901 T::fetch_accumulate(&self.primitive, value, f)
902 }
903
904 /// Replaces the value with the maximum of the current value and `value`.
905 ///
906 /// # Parameters
907 ///
908 /// * `value` - The value to compare with the current value.
909 ///
910 /// # Returns
911 ///
912 /// The value before the operation.
913 ///
914 /// # Example
915 ///
916 /// ```rust
917 /// use qubit_atomic::Atomic;
918 ///
919 /// let atomic = Atomic::new(3);
920 /// assert_eq!(atomic.fetch_max(10), 3);
921 /// assert_eq!(atomic.load(), 10);
922 /// ```
923 #[inline]
924 pub fn fetch_max(&self, value: T) -> T {
925 T::fetch_max(&self.primitive, value)
926 }
927
928 /// Replaces the value with the minimum of the current value and `value`.
929 ///
930 /// # Parameters
931 ///
932 /// * `value` - The value to compare with the current value.
933 ///
934 /// # Returns
935 ///
936 /// The value before the operation.
937 ///
938 /// # Example
939 ///
940 /// ```rust
941 /// use qubit_atomic::Atomic;
942 ///
943 /// let atomic = Atomic::new(10);
944 /// assert_eq!(atomic.fetch_min(3), 10);
945 /// assert_eq!(atomic.load(), 3);
946 /// ```
947 #[inline]
948 pub fn fetch_min(&self, value: T) -> T {
949 T::fetch_min(&self.primitive, value)
950 }
951}
952
953impl Atomic<bool> {
954 /// Stores `true` and returns the previous value.
955 ///
956 /// # Returns
957 ///
958 /// The previous value.
959 ///
960 /// # Example
961 ///
962 /// ```rust
963 /// use qubit_atomic::Atomic;
964 ///
965 /// let flag = Atomic::new(false);
966 /// assert_eq!(flag.fetch_set(), false);
967 /// assert!(flag.load());
968 /// ```
969 #[inline]
970 pub fn fetch_set(&self) -> bool {
971 self.primitive.fetch_set()
972 }
973
974 /// Stores `false` and returns the previous value.
975 ///
976 /// # Returns
977 ///
978 /// The previous value.
979 ///
980 /// # Example
981 ///
982 /// ```rust
983 /// use qubit_atomic::Atomic;
984 ///
985 /// let flag = Atomic::new(true);
986 /// assert_eq!(flag.fetch_clear(), true);
987 /// assert!(!flag.load());
988 /// ```
989 #[inline]
990 pub fn fetch_clear(&self) -> bool {
991 self.primitive.fetch_clear()
992 }
993
994 /// Negates the value and returns the previous value.
995 ///
996 /// # Returns
997 ///
998 /// The previous value.
999 ///
1000 /// # Example
1001 ///
1002 /// ```rust
1003 /// use qubit_atomic::Atomic;
1004 ///
1005 /// let flag = Atomic::new(false);
1006 /// assert_eq!(flag.fetch_not(), false);
1007 /// assert!(flag.load());
1008 /// ```
1009 #[inline]
1010 pub fn fetch_not(&self) -> bool {
1011 self.primitive.fetch_not()
1012 }
1013
1014 /// Applies logical AND and returns the previous value.
1015 ///
1016 /// # Parameters
1017 ///
1018 /// * `value` - The value to combine with the current value.
1019 ///
1020 /// # Returns
1021 ///
1022 /// The previous value.
1023 ///
1024 /// # Example
1025 ///
1026 /// ```rust
1027 /// use qubit_atomic::Atomic;
1028 ///
1029 /// let flag = Atomic::new(true);
1030 /// assert_eq!(flag.fetch_and(false), true);
1031 /// assert!(!flag.load());
1032 /// ```
1033 #[inline]
1034 pub fn fetch_and(&self, value: bool) -> bool {
1035 self.primitive.fetch_and(value)
1036 }
1037
1038 /// Applies logical OR and returns the previous value.
1039 ///
1040 /// # Parameters
1041 ///
1042 /// * `value` - The value to combine with the current value.
1043 ///
1044 /// # Returns
1045 ///
1046 /// The previous value.
1047 ///
1048 /// # Example
1049 ///
1050 /// ```rust
1051 /// use qubit_atomic::Atomic;
1052 ///
1053 /// let flag = Atomic::new(false);
1054 /// assert_eq!(flag.fetch_or(true), false);
1055 /// assert!(flag.load());
1056 /// ```
1057 #[inline]
1058 pub fn fetch_or(&self, value: bool) -> bool {
1059 self.primitive.fetch_or(value)
1060 }
1061
1062 /// Applies logical XOR and returns the previous value.
1063 ///
1064 /// # Parameters
1065 ///
1066 /// * `value` - The value to combine with the current value.
1067 ///
1068 /// # Returns
1069 ///
1070 /// The previous value.
1071 ///
1072 /// # Example
1073 ///
1074 /// ```rust
1075 /// use qubit_atomic::Atomic;
1076 ///
1077 /// let flag = Atomic::new(true);
1078 /// assert_eq!(flag.fetch_xor(true), true);
1079 /// assert!(!flag.load());
1080 /// ```
1081 #[inline]
1082 pub fn fetch_xor(&self, value: bool) -> bool {
1083 self.primitive.fetch_xor(value)
1084 }
1085
1086 /// Stores `new` only when the current value is `false`.
1087 ///
1088 /// # Parameters
1089 ///
1090 /// * `new` - The replacement value.
1091 ///
1092 /// # Returns
1093 ///
1094 /// `Ok(())` if the value was replaced.
1095 ///
1096 /// # Errors
1097 ///
1098 /// Returns `Err(true)` if the observed current value was already `true`.
1099 /// In that case, `new` is not stored.
1100 ///
1101 /// # Example
1102 ///
1103 /// ```rust
1104 /// use qubit_atomic::Atomic;
1105 ///
1106 /// let flag = Atomic::new(false);
1107 /// assert!(flag.set_if_false(true).is_ok());
1108 /// assert!(flag.load());
1109 /// assert!(flag.set_if_false(false).is_err());
1110 /// ```
1111 #[inline]
1112 pub fn set_if_false(&self, new: bool) -> Result<(), bool> {
1113 self.primitive.set_if_false(new)
1114 }
1115
1116 /// Stores `new` only when the current value is `true`.
1117 ///
1118 /// # Parameters
1119 ///
1120 /// * `new` - The replacement value.
1121 ///
1122 /// # Returns
1123 ///
1124 /// `Ok(())` if the value was replaced.
1125 ///
1126 /// # Errors
1127 ///
1128 /// Returns `Err(false)` if the observed current value was already `false`.
1129 /// In that case, `new` is not stored.
1130 ///
1131 /// # Example
1132 ///
1133 /// ```rust
1134 /// use qubit_atomic::Atomic;
1135 ///
1136 /// let flag = Atomic::new(true);
1137 /// assert!(flag.set_if_true(false).is_ok());
1138 /// assert!(!flag.load());
1139 /// assert!(flag.set_if_true(true).is_err());
1140 /// ```
1141 #[inline]
1142 pub fn set_if_true(&self, new: bool) -> Result<(), bool> {
1143 self.primitive.set_if_true(new)
1144 }
1145}
1146
1147impl<T> Default for Atomic<T>
1148where
1149 T: AtomicValue + Default,
1150{
1151 /// Creates an atomic with [`Default::default`] as the initial value.
1152 ///
1153 /// # Example
1154 ///
1155 /// ```rust
1156 /// use qubit_atomic::Atomic;
1157 ///
1158 /// let atomic = Atomic::<i32>::default();
1159 /// assert_eq!(atomic.load(), 0);
1160 /// ```
1161 #[inline]
1162 fn default() -> Self {
1163 Self::new(T::default())
1164 }
1165}
1166
1167impl<T> From<T> for Atomic<T>
1168where
1169 T: AtomicValue,
1170{
1171 /// Converts `value` into an [`Atomic`] via [`Atomic::new`].
1172 ///
1173 /// # Example
1174 ///
1175 /// ```rust
1176 /// use qubit_atomic::Atomic;
1177 ///
1178 /// let atomic = Atomic::from(42i32);
1179 /// assert_eq!(atomic.load(), 42);
1180 /// ```
1181 #[inline]
1182 fn from(value: T) -> Self {
1183 Self::new(value)
1184 }
1185}
1186
1187impl<T> fmt::Debug for Atomic<T>
1188where
1189 T: AtomicValue + fmt::Debug,
1190{
1191 /// Formats the loaded value as `Atomic { value: ... }`.
1192 ///
1193 /// # Example
1194 ///
1195 /// ```rust
1196 /// use qubit_atomic::Atomic;
1197 ///
1198 /// let atomic = Atomic::new(7);
1199 /// assert!(format!("{:?}", atomic).contains("7"));
1200 /// ```
1201 #[inline]
1202 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1203 f.debug_struct("Atomic")
1204 .field("value", &self.load())
1205 .finish()
1206 }
1207}
1208
1209impl<T> fmt::Display for Atomic<T>
1210where
1211 T: AtomicValue + fmt::Display,
1212{
1213 /// Formats the loaded value using its [`Display`](fmt::Display) implementation.
1214 ///
1215 /// # Example
1216 ///
1217 /// ```rust
1218 /// use qubit_atomic::Atomic;
1219 ///
1220 /// let atomic = Atomic::new(42);
1221 /// assert_eq!(format!("{}", atomic), "42");
1222 /// ```
1223 #[inline]
1224 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1225 write!(f, "{}", self.load())
1226 }
1227}