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