Crate thread_local

source ·
Expand description

Per-object thread-local storage

This library provides the ThreadLocal type which allows a separate copy of an object to be used for each thread. This allows for per-object thread-local storage, unlike the standard library’s thread_local! macro which only allows static thread-local storage.

Per-thread objects are not destroyed when a thread exits. Instead, objects are only destroyed when the ThreadLocal containing them is destroyed.

You can also iterate over the thread-local values of all thread in a ThreadLocal object using the iter_mut and into_iter methods. This can only be done if you have mutable access to the ThreadLocal object, which guarantees that you are the only thread currently accessing it.

A CachedThreadLocal type is also provided which wraps a ThreadLocal but also uses a special fast path for the first thread that writes into it. The fast path has very low overhead (<1ns per access) while keeping the same performance as ThreadLocal for other threads.

Note that since thread IDs are recycled when a thread exits, it is possible for one thread to retrieve the object of another thread. Since this can only occur after a thread has exited this does not lead to any race conditions.


Basic usage of ThreadLocal:

use thread_local::ThreadLocal;
let tls: ThreadLocal<u32> = ThreadLocal::new();
assert_eq!(tls.get(), None);
assert_eq!(tls.get_or(|| 5), &5);
assert_eq!(tls.get(), Some(&5));

Combining thread-local values into a single result:

use thread_local::ThreadLocal;
use std::sync::Arc;
use std::cell::Cell;
use std::thread;

let tls = Arc::new(ThreadLocal::new());

// Create a bunch of threads to do stuff
for _ in 0..5 {
    let tls2 = tls.clone();
    thread::spawn(move || {
        // Increment a counter to count some event...
        let cell = tls2.get_or(|| Cell::new(0));
        cell.set(cell.get() + 1);

// Once all threads are done, collect the counter values and return the
// sum of all thread-local counter values.
let tls = Arc::try_unwrap(tls).unwrap();
let total = tls.into_iter().fold(0, |x, y| x + y.get());
assert_eq!(total, 5);


An iterator that moves out of a CachedThreadLocal.
Mutable iterator over the contents of a CachedThreadLocal.
Wrapper around ThreadLocal which adds a fast path for a single thread.
An iterator that moves out of a ThreadLocal.
Mutable iterator over the contents of a ThreadLocal.
Thread-local variable wrapper