3 releases
0.1.2 | Aug 21, 2021 |
---|---|
0.1.1 | Jul 2, 2021 |
0.1.0 | Jun 19, 2021 |
#1068 in Concurrency
16KB
242 lines
thread-safe
This crate implements a simple container that allows thread-unsafe variables to be sent across threads, as long
as they are only directly accessed from the origin thread. This crate allows for breadthread
to not have any
unsafe code in it.
License
This crate is dual-licensed under the MIT and Apache 2.0 Licenses, just like Rust proper is.
lib.rs
:
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);