use core::marker::PhantomData;
#[cfg(target_has_atomic = "64")]
use alloc::sync::Arc;
#[cfg(target_has_atomic = "64")]
use core::cell::Cell;
#[cfg(target_has_atomic = "64")]
use core::sync::atomic::{AtomicU64, Ordering};
#[cfg(not(target_has_atomic = "64"))]
use triple_buffer::{Input, Output, TripleBuffer};
use crate::Data64Bit;
pub const fn is_atomic() -> bool {
#[cfg(target_has_atomic = "64")]
return true;
#[cfg(not(target_has_atomic = "64"))]
return false;
}
pub fn triple_buffer_64<T: Data64Bit>(val: T) -> (Input64<T>, Output64<T>) {
#[cfg(target_has_atomic = "64")]
{
let val = Arc::new(AtomicU64::new(u64::from_ne_bytes(T::to_ne_bytes(val))));
(
Input64 {
val: Arc::clone(&val),
_non_sync: PhantomData,
_data_type: PhantomData,
},
Output64 {
val,
_non_sync: PhantomData,
_data_type: PhantomData,
},
)
}
#[cfg(not(target_has_atomic = "64"))]
{
let data = T::to_ne_bytes(val);
let (input, output) = TripleBuffer::<[u8; 8]>::new(&data).split();
(
Input64 {
input,
_data_type: PhantomData,
},
Output64 {
output,
_data_type: PhantomData,
},
)
}
}
pub struct Input64<T: Data64Bit> {
#[cfg(target_has_atomic = "64")]
val: Arc<AtomicU64>,
#[cfg(target_has_atomic = "64")]
_non_sync: PhantomData<Cell<()>>,
#[cfg(not(target_has_atomic = "64"))]
input: Input<[u8; 8]>,
_data_type: PhantomData<T>,
}
impl<T: Data64Bit> Input64<T> {
pub fn write(&mut self, val: T) {
#[cfg(target_has_atomic = "64")]
self.val
.store(u64::from_ne_bytes(T::to_ne_bytes(val)), Ordering::Relaxed);
#[cfg(not(target_has_atomic = "64"))]
self.input.write(T::to_ne_bytes(val));
}
}
pub struct Output64<T: Data64Bit> {
#[cfg(target_has_atomic = "64")]
val: Arc<AtomicU64>,
#[cfg(target_has_atomic = "64")]
_non_sync: PhantomData<Cell<()>>,
#[cfg(not(target_has_atomic = "64"))]
output: Output<[u8; 8]>,
_data_type: PhantomData<T>,
}
impl<T: Data64Bit> Output64<T> {
pub fn read(&mut self) -> T {
#[cfg(target_has_atomic = "64")]
return T::from_ne_bytes(u64::to_ne_bytes(self.val.load(Ordering::Relaxed)));
#[cfg(not(target_has_atomic = "64"))]
return T::from_ne_bytes(*self.output.read());
}
}