Skip to main content

RayonSafeOnce

Struct RayonSafeOnce 

Source
pub struct RayonSafeOnce<T> { /* private fields */ }
Expand description

Lazy-init cache safe to call from inside rayon par_iter.

std::sync::OnceLock::get_or_init parks racing threads on an OS condition variable until the leader’s init closure finishes. If the leader’s init closure itself dispatches a nested into_par_iter, the parked threads are now unavailable as rayon workers, and the leader blocks waiting for chunks that no one can service. Classic deadlock.

RayonSafeOnce removes the trap by computing the value outside any lock. Concurrent racers may produce duplicate values; the first to publish wins, the rest drop their result. No thread ever parks waiting for another thread’s init to finish, so nested rayon par_iter inside the init closure is safe.

Use this in place of OnceLock whenever the init closure transitively runs rayon work and the cache may be entered concurrently from inside another rayon par_iter. The redundant-work cost on first race is the price for never deadlocking; in practice the loser threads throw away one round of work and steady-state is identical to OnceLock.

Implementations§

Source§

impl<T> RayonSafeOnce<T>

Source

pub const fn new() -> Self

Source

pub fn get(&self) -> Option<&T>

Returns the cached value if already populated.

Source

pub fn get_or_compute<F>(&self, init: F) -> &T
where F: FnOnce() -> T,

Returns the cached value, computing it if absent.

The init closure runs WITHOUT holding any lock — calls from concurrent rayon workers may all run it, and all but the first to call set discard their result. This is the contract that keeps nested into_par_iter inside init from deadlocking on other workers parked on a OnceLock.

Named get_or_compute (not get_or_init) so the codebase-level lint that bans OnceLock::get_or_init near rayon par_iter does not flag this safe-by-construction path.

Trait Implementations§

Source§

impl<T: Clone> Clone for RayonSafeOnce<T>

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<T: Debug> Debug for RayonSafeOnce<T>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<T> Default for RayonSafeOnce<T>

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

§

impl<T> !Freeze for RayonSafeOnce<T>

§

impl<T> RefUnwindSafe for RayonSafeOnce<T>

§

impl<T> Send for RayonSafeOnce<T>
where T: Send,

§

impl<T> Sync for RayonSafeOnce<T>
where T: Sync + Send,

§

impl<T> Unpin for RayonSafeOnce<T>
where T: Unpin,

§

impl<T> UnsafeUnpin for RayonSafeOnce<T>
where T: UnsafeUnpin,

§

impl<T> UnwindSafe for RayonSafeOnce<T>
where T: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.