prism3_atomic/atomic/
atomic_bool.rs

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