#![cfg_attr(feature = "nightly", feature(cfg_target_has_atomic))]
#![cfg_attr(not(test), no_std)]
#![forbid(unsafe_code)]
use bit_field::BitField as _;
use core::{
mem,
sync::atomic::{self, Ordering},
};
pub trait AtomicBitField: Sized {
#[inline]
fn bit_len() -> usize {
mem::size_of::<Self>() * 8
}
#[inline]
fn swap_bit(&self, bit: usize, new_val: bool, ord: Ordering) -> bool {
assert!(bit < Self::bit_len());
if new_val {
self.set_bit(bit, ord)
} else {
self.clear_bit(bit, ord)
}
}
fn get_bit(&self, bit: usize, ord: Ordering) -> bool;
fn set_bit(&self, bit: usize, ord: Ordering) -> bool;
fn clear_bit(&self, bit: usize, ord: Ordering) -> bool;
fn toggle_bit(&self, bit: usize, ord: Ordering) -> bool;
}
macro_rules! atomic_bitfield_impl_generate {
($($atomic_t:ty),*) => ($(
impl AtomicBitField for $atomic_t {
#[inline]
fn get_bit(&self, bit: usize, ord: Ordering) -> bool {
assert!(bit < Self::bit_len());
self.load(ord) & (1 << bit) != 0
}
#[inline]
fn set_bit(&self, bit: usize, ord: Ordering) -> bool {
assert!(bit < Self::bit_len());
let prev = self.fetch_or(1 << bit, ord);
prev.get_bit(bit)
}
#[inline]
fn clear_bit(&self, bit: usize, ord: Ordering) -> bool {
assert!(bit < Self::bit_len());
let prev = self.fetch_and(!(1 << bit), ord);
prev.get_bit(bit)
}
#[inline]
fn toggle_bit(&self, bit: usize, ord: Ordering) -> bool {
assert!(bit < Self::bit_len());
let prev = self.fetch_xor(1 << bit, ord);
prev.get_bit(bit)
}
}
)*)
}
cfg_if::cfg_if! {
if #[cfg(feature = "nightly")] {
#[cfg(target_has_atomic = "8")]
atomic_bitfield_impl_generate!(atomic::AtomicU8, atomic::AtomicI8);
#[cfg(target_has_atomic = "16")]
atomic_bitfield_impl_generate!(atomic::AtomicU16, atomic::AtomicI16);
#[cfg(target_has_atomic = "32")]
atomic_bitfield_impl_generate!(atomic::AtomicU32, atomic::AtomicI32);
#[cfg(target_has_atomic = "64")]
atomic_bitfield_impl_generate!(atomic::AtomicU64, atomic::AtomicI64);
#[cfg(target_has_atomic = "ptr")]
atomic_bitfield_impl_generate!(atomic::AtomicUsize, atomic::AtomicIsize);
} else {
use atomic::*;
atomic_bitfield_impl_generate!(AtomicU8, AtomicU16, AtomicU32, AtomicUsize, AtomicI8, AtomicI16, AtomicI32, AtomicIsize);
#[cfg(target_pointer_width = "64")]
atomic_bitfield_impl_generate!(AtomicU64, AtomicI64);
}
}
#[cfg(test)]
mod test;