use std::fmt;
use std::sync::atomic::Ordering;
use bitflags::Flags;
mod atomic_bits;
#[cfg(test)]
mod tests;
pub use atomic_bits::AtomicBits;
pub struct AtomicFlags<F>
where
F: Flags,
F::Bits: AtomicBits,
F: Copy,
{
storage: <F::Bits as AtomicBits>::Storage,
}
impl<F> Default for AtomicFlags<F>
where
F: Flags,
F::Bits: AtomicBits,
F: Copy,
F: Default,
{
fn default() -> Self {
Self::new(F::default())
}
}
impl<F> fmt::Debug for AtomicFlags<F>
where
F: Flags,
F::Bits: AtomicBits,
F: Copy,
F: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.load(Ordering::SeqCst).fmt(f)
}
}
impl<F> AtomicFlags<F>
where
F: Flags,
F::Bits: AtomicBits,
F: Copy,
{
pub fn new(flags: F) -> Self {
Self {
storage: F::Bits::new(flags.bits()),
}
}
pub fn store(&self, flags: F, ordering: Ordering) {
F::Bits::store(&self.storage, flags.bits(), ordering);
}
pub fn load(&self, ordering: Ordering) -> F {
F::from_bits_retain(F::Bits::load(&self.storage, ordering))
}
pub fn fetch_and(&self, flags: F, ordering: Ordering) -> F {
F::from_bits_retain(F::Bits::fetch_and(&self.storage, flags.bits(), ordering))
}
pub fn fetch_or(&self, flags: F, ordering: Ordering) -> F {
F::from_bits_retain(F::Bits::fetch_or(&self.storage, flags.bits(), ordering))
}
pub fn fetch_xor(&self, flags: F, ordering: Ordering) -> F {
F::from_bits_retain(F::Bits::fetch_xor(&self.storage, flags.bits(), ordering))
}
pub fn fetch_nand(&self, flags: F, ordering: Ordering) -> F {
F::from_bits_retain(F::Bits::fetch_nand(&self.storage, flags.bits(), ordering))
}
pub fn swap(&self, flags: F, ordering: Ordering) -> F {
F::from_bits_retain(F::Bits::swap(&self.storage, flags.bits(), ordering))
}
pub fn take(&self, flags: F, ordering: Ordering) -> F {
let previous = self.fetch_and(flags.complement(), ordering);
previous.intersection(flags)
}
pub fn peek(&self, flags: F, ordering: Ordering) -> F {
self.load(ordering).intersection(flags)
}
pub fn clear(&self, ordering: Ordering) {
self.store(F::empty(), ordering);
}
pub fn into_inner(self) -> F {
F::from_bits_retain(F::Bits::into_inner(self.storage))
}
pub fn set(&self, flags: F, ordering: Ordering) -> F {
self.fetch_or(flags, ordering)
}
pub fn unset(&self, flags: F, ordering: Ordering) -> F {
self.fetch_and(flags.complement(), ordering)
}
}