pub struct ThreadMap<V> { /* private fields */ }
Expand description
This type encapsulates the association of ThreadId
s to values of type V
. It is a simple and easy-to-use alternative
to the std::thread_local
macro and the thread_local
crate.
§Example
use std::{
sync::Arc,
thread::{self},
time::Duration,
};
use thread_map::ThreadMap;
const NTHREADS: i32 = 20;
const NITER: i32 = 10;
const SLEEP_MICROS: u64 = 10;
fn main() {
// There is no real need to wrap in `Arc` here because references can be used in scoped threads instead
// of clones, but the `Arc` wrapper would be required if non-scoped threads were used.
let tm: Arc<ThreadMap<i32>> = Arc::new(ThreadMap::default());
thread::scope(|s| {
for i in 0..NTHREADS {
let tm = tm.clone();
s.spawn(move || {
for _ in 0..NITER {
thread::sleep(Duration::from_micros(SLEEP_MICROS));
tm.with_mut(move |i0: &mut i32| *i0 += i);
}
let value = tm.get();
assert_eq!(i * NITER, value);
});
}
// Snapshot before thread-local value in main thread is updated.
let probed = tm.probe().unwrap();
println!("probed={probed:?}");
for _ in 0..NITER {
tm.with_mut(move |i0: &mut i32| *i0 += NTHREADS)
}
// Snapshot before all scoped threads terminate.
let probed = tm.probe().unwrap();
println!("\nprobed={probed:?}");
});
// Snapshot after all scoped threads terminate.
let probed = tm.probe().unwrap();
println!("\nprobed={probed:?}");
let expected_sum = (0..=NTHREADS).map(|i| i * NITER).sum::<i32>();
let sum = tm.fold_values(0, |z, v| z + v).unwrap();
assert_eq!(expected_sum, sum);
// Extracted values after all scoped threads terminate.
let dumped = tm.drain().unwrap();
println!("\ndumped={dumped:?}");
}
Implementations§
Source§impl<V> ThreadMap<V>
impl<V> ThreadMap<V>
Sourcepub fn new(value_init: fn() -> V) -> Self
pub fn new(value_init: fn() -> V) -> Self
Creates a new ThreadMap
instance, with value_init
used to create the initial value for each thread.
Sourcepub fn with_mut<W>(&self, f: impl FnOnce(&mut V) -> W) -> W
pub fn with_mut<W>(&self, f: impl FnOnce(&mut V) -> W) -> W
Invokes f
mutably on the value associated with the ThreadId
of the current thread and returns the invocation result.
If there is no value associated with the current thread then the value_init
argument of Self::new
is used
to instantiate an initial associated value before f
is applied.
§Panics
- If
self
’s lock is poisoned.
Sourcepub fn with<W>(&self, f: impl FnOnce(&V) -> W) -> W
pub fn with<W>(&self, f: impl FnOnce(&V) -> W) -> W
Invokes f
on the value associated with the ThreadId
of the current thread and returns the invocation result.
If there is no value associated with the current thread then the value_init
argument of Self::new
is used
to instantiate an initial associated value before f
is applied.
§Panics
- If
self
’s lock is poisoned.
Sourcepub fn get(&self) -> Vwhere
V: Clone,
pub fn get(&self) -> Vwhere
V: Clone,
Returns a clone of the value associated with the current thread.
§Panics
- If
self
’s lock is poisoned.
Sourcepub fn drain(&self) -> Result<HashMap<ThreadId, V>, ThreadMapLockError>
pub fn drain(&self) -> Result<HashMap<ThreadId, V>, ThreadMapLockError>
Returns a HashMap
with the values associated with each ThreadId
key and clears self
’s state.
§Errors
ThreadMapLockError
if the internal lock is poisoned.
Sourcepub fn fold<W>(
&self,
z: W,
f: impl FnMut(W, (ThreadId, &V)) -> W,
) -> Result<W, ThreadMapLockError>
pub fn fold<W>( &self, z: W, f: impl FnMut(W, (ThreadId, &V)) -> W, ) -> Result<W, ThreadMapLockError>
Folds every association in self
into an accumulator (with initial value z
) by applying an operation f
,
returning the final result.
§Errors
ThreadMapLockError
if the internal lock is poisoned.
Sourcepub fn fold_values<W>(
&self,
z: W,
f: impl FnMut(W, &V) -> W,
) -> Result<W, ThreadMapLockError>
pub fn fold_values<W>( &self, z: W, f: impl FnMut(W, &V) -> W, ) -> Result<W, ThreadMapLockError>
Folds every value in self
into an accumulator (with initial value z
) by applying an operation f
,
returning the final result.
§Errors
ThreadMapLockError
if the internal lock is poisoned.