use portable_atomic::{AtomicU64, AtomicU128};
#[repr(transparent)]
pub(crate) struct AtomicInt {
inner: AtomicU128,
}
impl AtomicInt {
pub(crate) fn new(value: u128) -> Self {
Self {
inner: AtomicU128::new(value),
}
}
#[inline]
pub(crate) fn as_u128(&self) -> &AtomicU128 {
&self.inner
}
#[inline]
pub(crate) fn as_u64(&self) -> &AtomicU64 {
let first_word = self.inner.as_ptr().cast::<u64>();
#[cfg(target_endian = "little")]
let low_word = first_word;
#[cfg(target_endian = "big")]
let low_word = unsafe { first_word.add(1) };
unsafe { AtomicU64::from_ptr(low_word) }
}
}
#[cfg(test)]
mod tests {
use super::*;
use portable_atomic::Ordering::Relaxed;
#[test]
fn views_share_the_numeric_low_half() {
let value = AtomicInt::new((0xfeed_face_cafe_beef_u128 << 64) | 41);
assert_eq!(value.as_u64().load(Relaxed), 41);
value.as_u64().store(42, Relaxed);
assert_eq!(
value.as_u128().load(Relaxed),
(0xfeed_face_cafe_beef_u128 << 64) | 42
);
}
}