#![cfg(feature = "atomic")]
use crate::bits::{
BitPos,
Bits,
};
use core::sync::atomic::{
AtomicU8,
AtomicU16,
AtomicU32,
Ordering,
};
#[cfg(target_pointer_width = "64")]
use core::sync::atomic::AtomicU64;
#[cfg_attr(not(feature = "std"), doc = "[`Relaxed`]: https://doc.rust-lang.org/stable/core/sync/atomic/enum.Ordering.html#variant.Relaxed")]
#[cfg_attr(feature = "std", doc = "[`Relaxed`]: https://doc.rust-lang.org/stable/std/sync/atomic/enum.Ordering.html#variant.Relaxed")]
pub trait Atomic<Fundamental: Sized>: Sized {
#[inline(always)]
fn clear(&self, bit: BitPos);
#[inline(always)]
fn set(&self, bit: BitPos);
#[inline(always)]
fn get(&self) -> Fundamental;
}
impl Atomic<u8> for AtomicU8 {
#[inline(always)]
fn clear(&self, bit: BitPos) {
self.fetch_and(!<u8 as Bits>::mask_at(bit), Ordering::Relaxed);
}
#[inline(always)]
fn set(&self, bit: BitPos) {
self.fetch_or(<u8 as Bits>::mask_at(bit), Ordering::Relaxed);
}
#[inline(always)]
fn get(&self) -> u8 {
self.load(Ordering::Relaxed)
}
}
impl Atomic<u16> for AtomicU16 {
#[inline(always)]
fn clear(&self, bit: BitPos) {
self.fetch_and(!<u16 as Bits>::mask_at(bit), Ordering::Relaxed);
}
#[inline(always)]
fn set(&self, bit: BitPos) {
self.fetch_or(<u16 as Bits>::mask_at(bit), Ordering::Relaxed);
}
#[inline(always)]
fn get(&self) -> u16 {
self.load(Ordering::Relaxed)
}
}
impl Atomic<u32> for AtomicU32 {
#[inline(always)]
fn clear(&self, bit: BitPos) {
self.fetch_and(!<u32 as Bits>::mask_at(bit), Ordering::Relaxed);
}
#[inline(always)]
fn set(&self, bit: BitPos) {
self.fetch_or(<u32 as Bits>::mask_at(bit), Ordering::Relaxed);
}
#[inline(always)]
fn get(&self) -> u32 {
self.load(Ordering::Relaxed)
}
}
#[cfg(target_pointer_width = "64")]
impl Atomic<u64> for AtomicU64 {
#[inline(always)]
fn clear(&self, bit: BitPos) {
self.fetch_and(!<u64 as Bits>::mask_at(bit), Ordering::Relaxed);
}
#[inline(always)]
fn set(&self, bit: BitPos) {
self.fetch_or(<u64 as Bits>::mask_at(bit), Ordering::Relaxed);
}
#[inline(always)]
fn get(&self) -> u64 {
self.load(Ordering::Relaxed)
}
}