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}