diff options
Diffstat (limited to 'engine/src/util.rs')
| -rw-r--r-- | engine/src/util.rs | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/engine/src/util.rs b/engine/src/util.rs index 439fe9a..454a776 100644 --- a/engine/src/util.rs +++ b/engine/src/util.rs @@ -1,3 +1,9 @@ +use std::fmt::Debug; +use std::mem::transmute; +use std::sync::atomic::Ordering; + +use portable_atomic::AtomicU128; + use crate::ecs::util::VecExt; #[derive(Debug)] @@ -94,6 +100,96 @@ impl<T> OptionExt<T> for Option<T> } } +pub struct AtomicTwoF64 +{ + inner: AtomicU128, +} + +impl AtomicTwoF64 +{ + pub const fn new((first, second): (f64, f64)) -> Self + { + let mut bytes = [0u8; size_of::<u128>()]; + + bytes.copy_from_slice([first.to_ne_bytes(), second.to_ne_bytes()].as_flattened()); + + Self { + inner: AtomicU128::new(u128::from_ne_bytes(bytes)), + } + } + + pub fn load(&self, order: Ordering) -> (f64, f64) + { + u128_to_two_f64(self.inner.load(order)) + } + + pub fn store(&self, values: (f64, f64), order: Ordering) + { + self.inner.store(two_f64_to_u128(values), order); + } + + pub fn swap(&self, values: (f64, f64), order: Ordering) -> (f64, f64) + { + u128_to_two_f64(self.inner.swap(two_f64_to_u128(values), order)) + } + + pub fn compare_exchange( + &self, + current: (f64, f64), + new: (f64, f64), + success_order: Ordering, + failure_order: Ordering, + ) -> Result<(f64, f64), (f64, f64)> + { + self.inner + .compare_exchange( + two_f64_to_u128(current), + two_f64_to_u128(new), + success_order, + failure_order, + ) + .map(|stored| u128_to_two_f64(stored)) + .map_err(|stored| u128_to_two_f64(stored)) + } +} + +impl Debug for AtomicTwoF64 +{ + fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result + { + let (first, second) = self.load(Ordering::Relaxed); + + formatter + .debug_tuple("AtomicTwoF64") + .field(&first) + .field(&second) + .finish() + } +} + +fn two_f64_to_u128((first, second): (f64, f64)) -> u128 +{ + let mut bytes = [0u8; size_of::<u128>()]; + + bytes.copy_from_slice([first.to_ne_bytes(), second.to_ne_bytes()].as_flattened()); + + u128::from_ne_bytes(bytes) +} + +fn u128_to_two_f64(src: u128) -> (f64, f64) +{ + let [first_bytes, second_bytes] = unsafe { + transmute::<[u8; size_of::<u128>()], [[u8; size_of::<f64>()]; 2]>( + src.to_ne_bytes(), + ) + }; + + ( + f64::from_ne_bytes(first_bytes), + f64::from_ne_bytes(second_bytes), + ) +} + macro_rules! try_option { ($expr: expr) => { match $expr { |
