Skip to content

Commit

Permalink
Add OnceNonZeroUsize::get_unchecked for x86/x86_64.
Browse files Browse the repository at this point in the history
Each call to `OnceNonZeroUsize::get()` results in an atomic load as the
compiler will not cache and reuse the result of an atomic load.

Provide an analogous `get_unchecked()` that uses a non-atomic load. The
compiler will be able to cache and reuse the result to avoid redundant
loads.
  • Loading branch information
briansmith committed Feb 6, 2025
1 parent 4fbd4a5 commit a5beabc
Showing 1 changed file with 23 additions and 0 deletions.
23 changes: 23 additions & 0 deletions src/race.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,29 @@ impl OnceNonZeroUsize {
NonZeroUsize::new(val)
}

/// Get the reference to the underlying value, without checking if the cell
/// is initialized.
///
/// # Safety
///
/// Caller must ensure that the cell is in initialized state, and that
/// the contents are acquired by (synchronized to) this thread.
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub fn get_unchecked(&self) -> NonZeroUsize {
let p = self.inner.as_ptr();
// SAFETY: The caller is responsible for ensuring that the value
// was initialized and that the contents have been acquired by
// this thread. This method is only made available on a subset of
// targets where we are confident there will be no tearing or other
// interference with another thread that may be setting the value
// simultaneously.
let val = unsafe { p.read() };

// SAFETY: The caller is responsible for ensuring the value is
// initialized and thus not zero.
unsafe { NonZeroUsize::new_unchecked(val) }
}

/// Sets the contents of this cell to `value`.
///
/// Returns `Ok(())` if the cell was empty and `Err(())` if it was
Expand Down

0 comments on commit a5beabc

Please sign in to comment.