Crate thread_safe[][src]

Expand description

Let’s say you have some thread-unsafe data. For whatever reason, it can’t be used outside of the thread it originated in. This thread-unsafe data is a component of a larger data struct that does need to be sent around between other threads.

The ThreadSafe contains data that can only be utilized in the thread it was created in. When a reference is attempted to be acquired to the interior data, it checks for the current thread it comes from.

ThreadKey

The ThreadKey is a wrapper around ThreadId, but !Send. This allows one to certify that the current thread has the given ThreadId, without having to go through thread::current().id().

Example

use std::{cell::Cell, sync::{Arc, atomic}, thread};
use thread_safe::ThreadSafe;

#[derive(Debug)]
struct InnerData {
    counter: atomic::AtomicUsize,
    other_counter: ThreadSafe<Cell<usize>>,
}

fn increment_data(data: &InnerData) {
    data.counter.fetch_add(1, atomic::Ordering::SeqCst);
    if let Ok(counter) = data.other_counter.try_get_ref() {
        counter.set(counter.get() + 1);
    }
}

let data = Arc::new(InnerData {
    counter: atomic::AtomicUsize::new(0),
    other_counter: ThreadSafe::new(Cell::new(0)),
});

let mut handles = vec![];

for _ in 0..10 {
    let data = data.clone();
    handles.push(thread::spawn(move || increment_data(&data)));
}

increment_data(&data);

for handle in handles {
    handle.join().unwrap();
}

let data = Arc::try_unwrap(data).unwrap();
assert_eq!(data.counter.load(atomic::Ordering::Relaxed), 11);
assert_eq!(data.other_counter.get_ref().get(), 1);

Structs

Error type for “we are not in the current thread”.

A ThreadId that is guaranteed to refer to the current thread, since this is !Send.

The whole point.