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}