Skip to main content

qubit_atomic/atomic/
atomic_bool.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//! # Atomic Boolean
12//!
13//! Provides an easy-to-use atomic boolean type with sensible default memory
14//! orderings.
15//!
16
17use std::sync::atomic::AtomicBool as StdAtomicBool;
18use std::sync::atomic::Ordering;
19
20use crate::atomic::atomic_ops::AtomicOps;
21
22/// Atomic boolean type.
23///
24/// Provides easy-to-use atomic operations with automatic memory ordering
25/// selection. All methods are thread-safe and can be shared across threads.
26///
27/// # Memory Ordering Strategy
28///
29/// This type uses carefully selected default memory orderings:
30///
31/// - **Read operations** (`load`): Use `Acquire` ordering to ensure that
32///   all writes from other threads that happened before a `Release` store
33///   are visible after this load.
34///
35/// - **Write operations** (`store`): Use `Release` ordering to ensure that
36///   all prior writes in this thread are visible to other threads that
37///   perform an `Acquire` load.
38///
39/// - **Read-Modify-Write operations** (`swap`, `compare_set`, `fetch_*`):
40///   Use `AcqRel` ordering to combine both `Acquire` and `Release`
41///   semantics, ensuring proper synchronization in both directions.
42///
43/// - **CAS failure**: Use `Acquire` ordering on failure to observe the
44///   actual value written by another thread.
45///
46/// These orderings provide a balance between performance and correctness
47/// for typical concurrent programming patterns.
48///
49/// # Features
50///
51/// - Automatic memory ordering selection
52/// - Rich set of boolean-specific operations
53/// - Zero-cost abstraction with inline methods
54/// - Access to underlying type via `inner()` for advanced use cases
55///
56/// # Example
57///
58/// ```rust
59/// use qubit_atomic::Atomic;
60/// use std::sync::Arc;
61/// use std::thread;
62///
63/// let flag = Arc::new(Atomic::<bool>::new(false));
64/// let flag_clone = flag.clone();
65///
66/// let handle = thread::spawn(move || {
67///     flag_clone.store(true);
68/// });
69///
70/// handle.join().unwrap();
71/// assert_eq!(flag.load(), true);
72/// ```
73///
74#[repr(transparent)]
75pub struct AtomicBool {
76    /// Standard-library atomic boolean used as the storage backend.
77    inner: StdAtomicBool,
78}
79
80impl AtomicBool {
81    /// Creates a new atomic boolean.
82    ///
83    /// # Parameters
84    ///
85    /// * `value` - The initial value.
86    ///
87    /// # Returns
88    ///
89    /// An atomic boolean initialized to `value`.
90    ///
91    /// # Example
92    ///
93    /// ```rust
94    /// use qubit_atomic::Atomic;
95    ///
96    /// let flag = Atomic::<bool>::new(false);
97    /// assert_eq!(flag.load(), false);
98    /// ```
99    #[inline]
100    pub const fn new(value: bool) -> Self {
101        Self {
102            inner: StdAtomicBool::new(value),
103        }
104    }
105
106    /// Gets the current value.
107    ///
108    /// # Memory Ordering
109    ///
110    /// Uses `Acquire` ordering. This ensures that:
111    /// - All writes from other threads that happened before a `Release`
112    ///   store are visible after this load.
113    /// - Forms a synchronizes-with relationship with `Release` stores.
114    /// - Prevents reordering of subsequent reads/writes before this load.
115    ///
116    /// This is appropriate for reading shared state that may have been
117    /// modified by other threads.
118    ///
119    /// # Returns
120    ///
121    /// The current value.
122    ///
123    /// # Example
124    ///
125    /// ```rust
126    /// use qubit_atomic::Atomic;
127    ///
128    /// let flag = Atomic::<bool>::new(true);
129    /// assert_eq!(flag.load(), true);
130    /// ```
131    #[inline]
132    pub fn load(&self) -> bool {
133        self.inner.load(Ordering::Acquire)
134    }
135
136    /// Sets a new value.
137    ///
138    /// # Memory Ordering
139    ///
140    /// Uses `Release` ordering. This ensures that:
141    /// - All prior writes in this thread are visible to other threads that
142    ///   perform an `Acquire` load.
143    /// - Forms a synchronizes-with relationship with `Acquire` loads.
144    /// - Prevents reordering of prior reads/writes after this store.
145    ///
146    /// This is appropriate for publishing shared state to other threads.
147    ///
148    /// # Parameters
149    ///
150    /// * `value` - The new value to set.
151    ///
152    /// # Example
153    ///
154    /// ```rust
155    /// use qubit_atomic::Atomic;
156    ///
157    /// let flag = Atomic::<bool>::new(false);
158    /// flag.store(true);
159    /// assert_eq!(flag.load(), true);
160    /// ```
161    #[inline]
162    pub fn store(&self, value: bool) {
163        self.inner.store(value, Ordering::Release);
164    }
165
166    /// Swaps the current value with a new value, returning the old value.
167    ///
168    /// # Memory Ordering
169    ///
170    /// Uses `AcqRel` ordering. This ensures that:
171    /// - **Acquire**: All writes from other threads that happened before
172    ///   their `Release` operations are visible after this operation.
173    /// - **Release**: All prior writes in this thread are visible to other
174    ///   threads that perform subsequent `Acquire` operations.
175    ///
176    /// This provides full synchronization for read-modify-write operations.
177    ///
178    /// # Parameters
179    ///
180    /// * `value` - The new value to swap in.
181    ///
182    /// # Returns
183    ///
184    /// The old value.
185    ///
186    /// # Example
187    ///
188    /// ```rust
189    /// use qubit_atomic::Atomic;
190    ///
191    /// let flag = Atomic::<bool>::new(false);
192    /// let old = flag.swap(true);
193    /// assert_eq!(old, false);
194    /// assert_eq!(flag.load(), true);
195    /// ```
196    #[inline]
197    pub fn swap(&self, value: bool) -> bool {
198        self.inner.swap(value, Ordering::AcqRel)
199    }
200
201    /// Compares and sets the value atomically.
202    ///
203    /// If the current value equals `current`, sets it to `new` and returns
204    /// `Ok(())`. Otherwise, returns `Err(actual)` where `actual` is the
205    /// current value.
206    ///
207    /// # Memory Ordering
208    ///
209    /// - **Success**: Uses `AcqRel` ordering to ensure full synchronization
210    ///   when the exchange succeeds.
211    /// - **Failure**: Uses `Acquire` ordering to observe the actual value
212    ///   written by another thread.
213    ///
214    /// This pattern is essential for implementing lock-free algorithms where
215    /// you need to retry based on the observed value.
216    ///
217    /// # Parameters
218    ///
219    /// * `current` - The expected current value.
220    /// * `new` - The new value to set if current matches.
221    ///
222    /// # Returns
223    ///
224    /// `Ok(())` when the value was replaced.
225    ///
226    /// # Errors
227    ///
228    /// Returns `Err(actual)` with the observed value when the comparison
229    /// fails. In that case, `new` is not stored.
230    ///
231    /// # Example
232    ///
233    /// ```rust
234    /// use qubit_atomic::Atomic;
235    ///
236    /// let flag = Atomic::<bool>::new(false);
237    /// assert!(flag.compare_set(false, true).is_ok());
238    /// assert_eq!(flag.load(), true);
239    ///
240    /// // Fails because current value is true, not false
241    /// assert!(flag.compare_set(false, false).is_err());
242    /// ```
243    #[inline]
244    pub fn compare_set(&self, current: bool, new: bool) -> Result<(), bool> {
245        self.inner
246            .compare_exchange(current, new, Ordering::AcqRel, Ordering::Acquire)
247            .map(|_| ())
248    }
249
250    /// Weak version of compare-and-set.
251    ///
252    /// May spuriously fail even when the comparison succeeds. Should be used
253    /// in a loop.
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 new value to set if current 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, including possible spurious failures. In that case, `new` is not
270    /// stored.
271    ///
272    /// # Example
273    ///
274    /// ```rust
275    /// use qubit_atomic::Atomic;
276    ///
277    /// let flag = Atomic::<bool>::new(false);
278    /// let mut current = flag.load();
279    /// loop {
280    ///     match flag.compare_set_weak(current, true) {
281    ///         Ok(_) => break,
282    ///         Err(actual) => current = actual,
283    ///     }
284    /// }
285    /// assert_eq!(flag.load(), true);
286    /// ```
287    #[inline]
288    pub fn compare_set_weak(&self, current: bool, new: bool) -> Result<(), bool> {
289        self.inner
290            .compare_exchange_weak(current, new, Ordering::AcqRel, Ordering::Acquire)
291            .map(|_| ())
292    }
293
294    /// Compares and exchanges the value atomically, returning the previous
295    /// value.
296    ///
297    /// If the current value equals `current`, sets it to `new` and returns
298    /// the old value. Otherwise, returns the actual current value.
299    ///
300    /// Uses `AcqRel` ordering on success and `Acquire` ordering on failure.
301    ///
302    /// # Parameters
303    ///
304    /// * `current` - The expected current value.
305    /// * `new` - The new value to set if current matches.
306    ///
307    /// # Returns
308    ///
309    /// The value observed before the operation completed. If the returned
310    /// value equals `current`, the exchange succeeded; otherwise it is the
311    /// actual value that prevented the exchange.
312    ///
313    /// # Example
314    ///
315    /// ```rust
316    /// use qubit_atomic::Atomic;
317    ///
318    /// let flag = Atomic::<bool>::new(false);
319    /// let prev = flag.compare_and_exchange(false, true);
320    /// assert_eq!(prev, false);
321    /// assert_eq!(flag.load(), true);
322    /// ```
323    #[inline]
324    pub fn compare_and_exchange(&self, current: bool, new: bool) -> bool {
325        match self
326            .inner
327            .compare_exchange(current, new, Ordering::AcqRel, Ordering::Acquire)
328        {
329            Ok(prev) => prev,
330            Err(actual) => actual,
331        }
332    }
333
334    /// Weak version of compare-and-exchange.
335    ///
336    /// May spuriously fail even when the comparison succeeds. Should be used
337    /// in a loop.
338    ///
339    /// Uses `AcqRel` ordering on success and `Acquire` ordering on failure.
340    ///
341    /// # Parameters
342    ///
343    /// * `current` - The expected current value.
344    /// * `new` - The new value to set if current matches.
345    ///
346    /// # Returns
347    ///
348    /// The value observed before the operation completed. Because this
349    /// operation may fail spuriously, a returned value equal to `current` does
350    /// not by itself prove that `new` was stored; use
351    /// [`compare_set_weak`](Self::compare_set_weak) when the caller needs an
352    /// explicit success indicator.
353    ///
354    /// # Example
355    ///
356    /// ```rust
357    /// use qubit_atomic::Atomic;
358    ///
359    /// let flag = Atomic::<bool>::new(false);
360    /// let mut current = flag.load();
361    /// loop {
362    ///     let prev = flag.compare_and_exchange_weak(current, true);
363    ///     if flag.load() {
364    ///         break;
365    ///     }
366    ///     current = prev;
367    /// }
368    /// assert_eq!(flag.load(), true);
369    /// ```
370    #[inline]
371    pub fn compare_and_exchange_weak(&self, current: bool, new: bool) -> bool {
372        match self
373            .inner
374            .compare_exchange_weak(current, new, Ordering::AcqRel, Ordering::Acquire)
375        {
376            Ok(prev) => prev,
377            Err(actual) => actual,
378        }
379    }
380
381    /// Atomically sets the value to `true`, returning the old value.
382    ///
383    /// # Memory Ordering
384    ///
385    /// Uses `AcqRel` ordering (via `swap`). This ensures full
386    /// synchronization with other threads for this read-modify-write
387    /// operation.
388    ///
389    /// # Returns
390    ///
391    /// The old value before setting to `true`.
392    ///
393    /// # Example
394    ///
395    /// ```rust
396    /// use qubit_atomic::Atomic;
397    ///
398    /// let flag = Atomic::<bool>::new(false);
399    /// let old = flag.fetch_set();
400    /// assert_eq!(old, false);
401    /// assert_eq!(flag.load(), true);
402    /// ```
403    #[inline]
404    pub fn fetch_set(&self) -> bool {
405        self.swap(true)
406    }
407
408    /// Atomically sets the value to `false`, returning the old value.
409    ///
410    /// # Memory Ordering
411    ///
412    /// Uses `AcqRel` ordering (via `swap`). This ensures full
413    /// synchronization with other threads for this read-modify-write
414    /// operation.
415    ///
416    /// # Returns
417    ///
418    /// The old value before setting to `false`.
419    ///
420    /// # Example
421    ///
422    /// ```rust
423    /// use qubit_atomic::Atomic;
424    ///
425    /// let flag = Atomic::<bool>::new(true);
426    /// let old = flag.fetch_clear();
427    /// assert_eq!(old, true);
428    /// assert_eq!(flag.load(), false);
429    /// ```
430    #[inline]
431    pub fn fetch_clear(&self) -> bool {
432        self.swap(false)
433    }
434
435    /// Atomically negates the value, returning the old value.
436    ///
437    /// # Memory Ordering
438    ///
439    /// Uses `AcqRel` ordering. This ensures full synchronization with other
440    /// threads for this read-modify-write operation.
441    ///
442    /// # Returns
443    ///
444    /// The old value before negation.
445    ///
446    /// # Example
447    ///
448    /// ```rust
449    /// use qubit_atomic::Atomic;
450    ///
451    /// let flag = Atomic::<bool>::new(false);
452    /// assert_eq!(flag.fetch_not(), false);
453    /// assert_eq!(flag.load(), true);
454    /// assert_eq!(flag.fetch_not(), true);
455    /// assert_eq!(flag.load(), false);
456    /// ```
457    #[inline]
458    pub fn fetch_not(&self) -> bool {
459        self.inner.fetch_xor(true, Ordering::AcqRel)
460    }
461
462    /// Atomically performs logical AND, returning the old value.
463    ///
464    /// # Memory Ordering
465    ///
466    /// Uses `AcqRel` ordering. This ensures full synchronization with other
467    /// threads for this read-modify-write operation, which is necessary
468    /// because the operation depends on the current value.
469    ///
470    /// # Parameters
471    ///
472    /// * `value` - The value to AND with.
473    ///
474    /// # Returns
475    ///
476    /// The old value before the operation.
477    ///
478    /// # Example
479    ///
480    /// ```rust
481    /// use qubit_atomic::Atomic;
482    ///
483    /// let flag = Atomic::<bool>::new(true);
484    /// assert_eq!(flag.fetch_and(false), true);
485    /// assert_eq!(flag.load(), false);
486    /// ```
487    #[inline]
488    pub fn fetch_and(&self, value: bool) -> bool {
489        self.inner.fetch_and(value, Ordering::AcqRel)
490    }
491
492    /// Atomically performs logical OR, returning the old value.
493    ///
494    /// # Memory Ordering
495    ///
496    /// Uses `AcqRel` ordering. This ensures full synchronization with other
497    /// threads for this read-modify-write operation, which is necessary
498    /// because the operation depends on the current value.
499    ///
500    /// # Parameters
501    ///
502    /// * `value` - The value to OR with.
503    ///
504    /// # Returns
505    ///
506    /// The old value before the operation.
507    ///
508    /// # Example
509    ///
510    /// ```rust
511    /// use qubit_atomic::Atomic;
512    ///
513    /// let flag = Atomic::<bool>::new(false);
514    /// assert_eq!(flag.fetch_or(true), false);
515    /// assert_eq!(flag.load(), true);
516    /// ```
517    #[inline]
518    pub fn fetch_or(&self, value: bool) -> bool {
519        self.inner.fetch_or(value, Ordering::AcqRel)
520    }
521
522    /// Atomically performs logical XOR, returning the old value.
523    ///
524    /// # Memory Ordering
525    ///
526    /// Uses `AcqRel` ordering. This ensures full synchronization with other
527    /// threads for this read-modify-write operation, which is necessary
528    /// because the operation depends on the current value.
529    ///
530    /// # Parameters
531    ///
532    /// * `value` - The value to XOR with.
533    ///
534    /// # Returns
535    ///
536    /// The old value before the operation.
537    ///
538    /// # Example
539    ///
540    /// ```rust
541    /// use qubit_atomic::Atomic;
542    ///
543    /// let flag = Atomic::<bool>::new(false);
544    /// assert_eq!(flag.fetch_xor(true), false);
545    /// assert_eq!(flag.load(), true);
546    /// ```
547    #[inline]
548    pub fn fetch_xor(&self, value: bool) -> bool {
549        self.inner.fetch_xor(value, Ordering::AcqRel)
550    }
551
552    /// Conditionally sets the value if it is currently `false`.
553    ///
554    /// Uses `AcqRel` ordering on success and `Acquire` ordering on failure.
555    ///
556    /// # Parameters
557    ///
558    /// * `new` - The new value to set if current is `false`.
559    ///
560    /// # Returns
561    ///
562    /// `Ok(())` if the value was `false` and has been set to `new`.
563    ///
564    /// # Errors
565    ///
566    /// Returns `Err(true)` if the value was already `true`. In that case,
567    /// `new` is not stored.
568    ///
569    /// # Example
570    ///
571    /// ```rust
572    /// use qubit_atomic::Atomic;
573    ///
574    /// let flag = Atomic::<bool>::new(false);
575    /// assert!(flag.set_if_false(true).is_ok());
576    /// assert_eq!(flag.load(), true);
577    ///
578    /// // Second attempt fails
579    /// assert!(flag.set_if_false(true).is_err());
580    /// ```
581    #[inline]
582    pub fn set_if_false(&self, new: bool) -> Result<(), bool> {
583        self.compare_set(false, new)
584    }
585
586    /// Conditionally sets the value if it is currently `true`.
587    ///
588    /// Uses `AcqRel` ordering on success and `Acquire` ordering on failure.
589    ///
590    /// # Parameters
591    ///
592    /// * `new` - The new value to set if current is `true`.
593    ///
594    /// # Returns
595    ///
596    /// `Ok(())` if the value was `true` and has been set to `new`.
597    ///
598    /// # Errors
599    ///
600    /// Returns `Err(false)` if the value was already `false`. In that case,
601    /// `new` is not stored.
602    ///
603    /// # Example
604    ///
605    /// ```rust
606    /// use qubit_atomic::Atomic;
607    ///
608    /// let flag = Atomic::<bool>::new(true);
609    /// assert!(flag.set_if_true(false).is_ok());
610    /// assert_eq!(flag.load(), false);
611    ///
612    /// // Second attempt fails
613    /// assert!(flag.set_if_true(false).is_err());
614    /// ```
615    #[inline]
616    pub fn set_if_true(&self, new: bool) -> Result<(), bool> {
617        self.compare_set(true, new)
618    }
619
620    /// Updates the value using a function, returning the old value.
621    ///
622    /// Internally uses a CAS loop until the update succeeds.
623    ///
624    /// # Parameters
625    ///
626    /// * `f` - A function that takes the current value and returns the new
627    ///   value.
628    ///
629    /// # Returns
630    ///
631    /// The old value before the update.
632    ///
633    /// The closure may be called more than once when concurrent updates cause
634    /// CAS retries.
635    ///
636    /// # Example
637    ///
638    /// ```rust
639    /// use qubit_atomic::Atomic;
640    ///
641    /// let flag = Atomic::<bool>::new(false);
642    /// assert_eq!(flag.fetch_update(|current| !current), false);
643    /// assert_eq!(flag.load(), true);
644    /// ```
645    #[inline]
646    pub fn fetch_update<F>(&self, f: F) -> bool
647    where
648        F: Fn(bool) -> bool,
649    {
650        let mut current = self.load();
651        loop {
652            let new = f(current);
653            match self.compare_set_weak(current, new) {
654                Ok(_) => return current,
655                Err(actual) => current = actual,
656            }
657        }
658    }
659
660    /// Conditionally updates the value using a function.
661    ///
662    /// Internally uses a CAS loop until the update succeeds or the closure
663    /// rejects the current value by returning `None`.
664    ///
665    /// # Parameters
666    ///
667    /// * `f` - A function that takes the current value and returns the new
668    ///   value, or `None` to leave the value unchanged.
669    ///
670    /// # Returns
671    ///
672    /// `Some(old_value)` when the update succeeds, or `None` when `f` rejects
673    /// the observed current value.
674    ///
675    /// The closure may be called more than once when concurrent updates cause
676    /// CAS retries.
677    ///
678    /// # Example
679    ///
680    /// ```rust
681    /// use qubit_atomic::Atomic;
682    ///
683    /// let flag = Atomic::<bool>::new(false);
684    /// assert_eq!(flag.try_update(|current| (!current).then_some(true)), Some(false));
685    /// assert_eq!(flag.load(), true);
686    /// assert_eq!(flag.try_update(|current| (!current).then_some(true)), None);
687    /// assert_eq!(flag.load(), true);
688    /// ```
689    #[inline]
690    pub fn try_update<F>(&self, f: F) -> Option<bool>
691    where
692        F: Fn(bool) -> Option<bool>,
693    {
694        let mut current = self.load();
695        loop {
696            let new = f(current)?;
697            match self.compare_set_weak(current, new) {
698                Ok(_) => return Some(current),
699                Err(actual) => current = actual,
700            }
701        }
702    }
703
704    /// Gets a reference to the underlying standard library atomic type.
705    ///
706    /// This allows direct access to the standard library's atomic operations
707    /// for advanced use cases that require fine-grained control over memory
708    /// ordering.
709    ///
710    /// # Memory Ordering
711    ///
712    /// When using the returned reference, you have full control over memory
713    /// ordering. Choose the appropriate ordering based on your specific
714    /// synchronization requirements.
715    ///
716    /// # Returns
717    ///
718    /// A reference to the underlying `std::sync::atomic::AtomicBool`.
719    ///
720    /// # Example
721    ///
722    /// ```rust
723    /// use qubit_atomic::Atomic;
724    /// use std::sync::atomic::Ordering;
725    ///
726    /// let flag = Atomic::<bool>::new(false);
727    /// flag.inner().store(true, Ordering::Relaxed);
728    /// assert_eq!(flag.inner().load(Ordering::Relaxed), true);
729    /// ```
730    #[inline]
731    pub fn inner(&self) -> &StdAtomicBool {
732        &self.inner
733    }
734}
735
736impl AtomicOps for AtomicBool {
737    type Value = bool;
738
739    #[inline]
740    fn load(&self) -> bool {
741        self.load()
742    }
743
744    #[inline]
745    fn store(&self, value: bool) {
746        self.store(value);
747    }
748
749    #[inline]
750    fn swap(&self, value: bool) -> bool {
751        self.swap(value)
752    }
753
754    #[inline]
755    fn compare_set(&self, current: bool, new: bool) -> Result<(), bool> {
756        self.compare_set(current, new)
757    }
758
759    #[inline]
760    fn compare_set_weak(&self, current: bool, new: bool) -> Result<(), bool> {
761        self.compare_set_weak(current, new)
762    }
763
764    #[inline]
765    fn compare_exchange(&self, current: bool, new: bool) -> bool {
766        self.compare_and_exchange(current, new)
767    }
768
769    #[inline]
770    fn compare_exchange_weak(&self, current: bool, new: bool) -> bool {
771        self.compare_and_exchange_weak(current, new)
772    }
773
774    #[inline]
775    fn fetch_update<F>(&self, f: F) -> bool
776    where
777        F: Fn(bool) -> bool,
778    {
779        self.fetch_update(f)
780    }
781
782    #[inline]
783    fn try_update<F>(&self, f: F) -> Option<bool>
784    where
785        F: Fn(bool) -> Option<bool>,
786    {
787        self.try_update(f)
788    }
789}