use std::sync::atomic::Ordering;
use crate::Float;
#[cfg(feature = "float-as-double")]
mod float {
pub(super) type UsizeFloat = u64;
pub(super) type AtomicUsizeFloat = std::sync::atomic::AtomicU64;
}
#[cfg(not(feature = "float-as-double"))]
mod float {
pub(super) type UsizeFloat = u32;
pub(super) type AtomicUsizeFloat = std::sync::atomic::AtomicU32;
}
use float::AtomicUsizeFloat;
use float::UsizeFloat;
#[derive(Debug)]
pub struct AtomicFloat {
bits: AtomicUsizeFloat,
}
impl From<Float> for AtomicFloat {
fn from(f: Float) -> Self {
AtomicFloat {
bits: AtomicUsizeFloat::new(f.to_bits()),
}
}
}
impl AtomicFloat {
pub fn get(&self) -> Float {
Float::from_bits(self.bits.load(Ordering::Relaxed))
}
pub fn add(&self, v: Float) {
let mut old_bits = self.bits.load(Ordering::Relaxed);
loop {
let new_bits: UsizeFloat = (Float::from_bits(old_bits) + v).to_bits();
match self.bits.compare_exchange_weak(
old_bits,
new_bits,
Ordering::SeqCst,
Ordering::SeqCst,
) {
Ok(_) => break,
Err(x) => old_bits = x,
}
}
}
}
impl Into<Float> for AtomicFloat {
fn into(self) -> Float {
Float::from_bits(self.bits.load(Ordering::Relaxed))
}
}