use std::sync::atomic::AtomicBool as StdAtomicBool;
use std::sync::atomic::Ordering;
use crate::atomic::atomic_ops::AtomicOps;
#[repr(transparent)]
pub struct AtomicBool {
inner: StdAtomicBool,
}
impl AtomicBool {
#[inline]
pub const fn new(value: bool) -> Self {
Self {
inner: StdAtomicBool::new(value),
}
}
#[inline]
pub fn load(&self) -> bool {
self.inner.load(Ordering::Acquire)
}
#[inline]
pub fn store(&self, value: bool) {
self.inner.store(value, Ordering::Release);
}
#[inline]
pub fn swap(&self, value: bool) -> bool {
self.inner.swap(value, Ordering::AcqRel)
}
#[inline]
pub fn compare_set(&self, current: bool, new: bool) -> Result<(), bool> {
self.inner
.compare_exchange(current, new, Ordering::AcqRel, Ordering::Acquire)
.map(|_| ())
}
#[inline]
pub fn compare_set_weak(&self, current: bool, new: bool) -> Result<(), bool> {
self.inner
.compare_exchange_weak(current, new, Ordering::AcqRel, Ordering::Acquire)
.map(|_| ())
}
#[inline]
pub fn compare_and_exchange(&self, current: bool, new: bool) -> bool {
match self
.inner
.compare_exchange(current, new, Ordering::AcqRel, Ordering::Acquire)
{
Ok(prev) => prev,
Err(actual) => actual,
}
}
#[inline]
pub fn compare_and_exchange_weak(&self, current: bool, new: bool) -> bool {
match self
.inner
.compare_exchange_weak(current, new, Ordering::AcqRel, Ordering::Acquire)
{
Ok(prev) => prev,
Err(actual) => actual,
}
}
#[inline]
pub fn fetch_set(&self) -> bool {
self.swap(true)
}
#[inline]
pub fn fetch_clear(&self) -> bool {
self.swap(false)
}
#[inline]
pub fn fetch_not(&self) -> bool {
self.inner.fetch_xor(true, Ordering::AcqRel)
}
#[inline]
pub fn fetch_and(&self, value: bool) -> bool {
self.inner.fetch_and(value, Ordering::AcqRel)
}
#[inline]
pub fn fetch_or(&self, value: bool) -> bool {
self.inner.fetch_or(value, Ordering::AcqRel)
}
#[inline]
pub fn fetch_xor(&self, value: bool) -> bool {
self.inner.fetch_xor(value, Ordering::AcqRel)
}
#[inline]
pub fn set_if_false(&self, new: bool) -> Result<(), bool> {
self.compare_set(false, new)
}
#[inline]
pub fn set_if_true(&self, new: bool) -> Result<(), bool> {
self.compare_set(true, new)
}
#[inline]
pub fn fetch_update<F>(&self, f: F) -> bool
where
F: Fn(bool) -> bool,
{
let mut current = self.load();
loop {
let new = f(current);
match self.compare_set_weak(current, new) {
Ok(_) => return current,
Err(actual) => current = actual,
}
}
}
#[inline]
pub fn try_update<F>(&self, f: F) -> Option<bool>
where
F: Fn(bool) -> Option<bool>,
{
let mut current = self.load();
loop {
let new = f(current)?;
match self.compare_set_weak(current, new) {
Ok(_) => return Some(current),
Err(actual) => current = actual,
}
}
}
#[inline]
pub fn inner(&self) -> &StdAtomicBool {
&self.inner
}
}
impl AtomicOps for AtomicBool {
type Value = bool;
#[inline]
fn load(&self) -> bool {
self.load()
}
#[inline]
fn store(&self, value: bool) {
self.store(value);
}
#[inline]
fn swap(&self, value: bool) -> bool {
self.swap(value)
}
#[inline]
fn compare_set(&self, current: bool, new: bool) -> Result<(), bool> {
self.compare_set(current, new)
}
#[inline]
fn compare_set_weak(&self, current: bool, new: bool) -> Result<(), bool> {
self.compare_set_weak(current, new)
}
#[inline]
fn compare_exchange(&self, current: bool, new: bool) -> bool {
self.compare_and_exchange(current, new)
}
#[inline]
fn compare_exchange_weak(&self, current: bool, new: bool) -> bool {
self.compare_and_exchange_weak(current, new)
}
#[inline]
fn fetch_update<F>(&self, f: F) -> bool
where
F: Fn(bool) -> bool,
{
self.fetch_update(f)
}
#[inline]
fn try_update<F>(&self, f: F) -> Option<bool>
where
F: Fn(bool) -> Option<bool>,
{
self.try_update(f)
}
}