//! Implementation of an atomic u64 cell. On 64 bit platforms, this is a //! re-export of `AtomicU64`. On 32 bit platforms, this is implemented using a //! `Mutex`. // `AtomicU64` can only be used on targets with `target_has_atomic` is 64 or greater. // Once `cfg_target_has_atomic` feature is stable, we can replace it with // `#[cfg(target_has_atomic = "64")]`. // Refs: https://github.com/rust-lang/rust/tree/master/src/librustc_target cfg_has_atomic_u64! { pub(crate) use std::sync::atomic::AtomicU64; } cfg_not_has_atomic_u64! { use crate::loom::sync::Mutex; use std::sync::atomic::Ordering; #[derive(Debug)] pub(crate) struct AtomicU64 { inner: Mutex, } impl AtomicU64 { pub(crate) fn new(val: u64) -> Self { Self { inner: Mutex::new(val), } } pub(crate) fn load(&self, _: Ordering) -> u64 { *self.inner.lock() } pub(crate) fn store(&self, val: u64, _: Ordering) { *self.inner.lock() = val; } pub(crate) fn fetch_add(&self, val: u64, _: Ordering) -> u64 { let mut lock = self.inner.lock(); let prev = *lock; *lock = prev + val; prev } pub(crate) fn fetch_or(&self, val: u64, _: Ordering) -> u64 { let mut lock = self.inner.lock(); let prev = *lock; *lock = prev | val; prev } pub(crate) fn compare_exchange( &self, current: u64, new: u64, _success: Ordering, _failure: Ordering, ) -> Result { let mut lock = self.inner.lock(); if *lock == current { *lock = new; Ok(current) } else { Err(*lock) } } pub(crate) fn compare_exchange_weak( &self, current: u64, new: u64, success: Ordering, failure: Ordering, ) -> Result { self.compare_exchange(current, new, success, failure) } } }