pub struct ThreadLocalCtx<T, F> { /* private fields */ }Expand description
A thread local storage container for Rayon jobs
This context can be used to efficiently clone inner, only when it’s necessary.
Implementations§
Source§impl<T, F: Fn() -> T> ThreadLocalCtx<T, F>
impl<T, F: Fn() -> T> ThreadLocalCtx<T, F>
Sourcepub fn new(inner: F) -> Self
pub fn new(inner: F) -> Self
Create a new TlsCtx
§Examples
Creating a thread-local byte buffer:
use rayon_tlsctx::ThreadLocalCtx;
let ctx = ThreadLocalCtx::new(Vec::<u8>::new);Sourcepub fn new_locked(inner: F) -> ThreadLocalCtx<T, impl Fn() -> T>
pub fn new_locked(inner: F) -> ThreadLocalCtx<T, impl Fn() -> T>
Create a new TlsCtx.
This context utilises a lock for cloning values, making it usable for non-sync types.
Cloning an initialised buffer for each thread:
use rayon_tlsctx::ThreadLocalCtx;
use rayon::iter::*;
use std::cell::Cell;
let mut buf: Vec<u16> = (0..!0).collect();
buf.shuffle(&mut rng);
let buf = (buf, Cell::new(0));
// Must use new_locked, because cloning a cell across threads is not allowed
let ctx = ThreadLocalCtx::new_locked(move || buf.clone());
(0..16).into_par_iter().for_each(|_| unsafe { ctx.get(); });Sourcepub unsafe fn get(&self) -> ThreadLocalMut<'_, T>
pub unsafe fn get(&self) -> ThreadLocalMut<'_, T>
Get a thread local context reference with dynamically checked borrow rules
§Remarks
It is advised to manually drop the borrowed context if it is to be reborrowed within inner scope. This is because chances of heap allocations significantly increase.
§Safety
Only one thread pool should use this scope (throughout the duration of its lifetime). The thread pool size can not grow midway through.
§Examples
use rayon_tlsctx::ThreadLocalCtx;
use rayon::iter::*;
const NUM_COPIES: usize = 16;
let mut buf: Vec<u16> = (0..!0).collect();
// Create a thread local context with value 0.
let ctx = ThreadLocalCtx::new(|| 0);
// Sum the buffer `NUM_COPIES` times and accumulate the results
// into the threaded pool of counts. Note that the counts may be
// Unevenly distributed.
(0..NUM_COPIES)
.into_par_iter()
.flat_map(|_| buf.par_iter())
.for_each(|i| {
let mut cnt = unsafe { ctx.get() };
*cnt += *i as usize;
});
let buf_sum = buf.into_iter().fold(0, |acc, i| acc + i as usize);
// What matters is that the final sum matches the expected value.
assert_eq!(ctx.into_iter().sum::<usize>(), buf_sum * NUM_COPIES);Trait Implementations§
Source§impl<T, F> IntoIterator for ThreadLocalCtx<T, F>
Consume the context and retrieve all created items.
impl<T, F> IntoIterator for ThreadLocalCtx<T, F>
Consume the context and retrieve all created items.
impl<T, F: Send + Sync> Send for ThreadLocalCtx<T, F>
impl<T, F: Send + Sync> Sync for ThreadLocalCtx<T, F>
Auto Trait Implementations§
impl<T, F> !Freeze for ThreadLocalCtx<T, F>
impl<T, F> !RefUnwindSafe for ThreadLocalCtx<T, F>
impl<T, F> Unpin for ThreadLocalCtx<T, F>
impl<T, F> UnsafeUnpin for ThreadLocalCtx<T, F>where
F: UnsafeUnpin,
impl<T, F> UnwindSafe for ThreadLocalCtx<T, F>where
F: UnwindSafe,
T: RefUnwindSafe,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
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