Name Description Size
lib.rs [![github]](https://github.com/dtolnay/threadbound)&ensp;[![crates-io]](https://crates.io/crates/threadbound)&ensp;[![docs-rs]](https://docs.rs/threadbound) [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs <br> [`ThreadBound<T>`] is a wrapper that binds a value to its original thread. The wrapper gets to be [`Sync`] and [`Send`] but only the original thread on which the ThreadBound was constructed can retrieve the underlying value. [`ThreadBound<T>`]: struct.ThreadBound.html [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html # Example ``` use std::marker::PhantomData; use std::rc::Rc; use std::sync::Arc; use threadbound::ThreadBound; // Neither Send nor Sync. Maybe the index points into a // thread-local interner. #[derive(Copy, Clone)] struct Span { index: u32, marker: PhantomData<Rc<()>>, } // Error types are always supposed to be Send and Sync. // We can use ThreadBound to make it so. struct Error { span: ThreadBound<Span>, message: String, } fn main() { let err = Error { span: ThreadBound::new(Span { index: 99, marker: PhantomData, }), message: "fearless concurrency".to_owned(), }; // Original thread can see the contents. assert_eq!(err.span.get_ref().unwrap().index, 99); let err = Arc::new(err); let err2 = err.clone(); std::thread::spawn(move || { // Other threads cannot get access. Maybe they use // a default value or a different codepath. assert!(err2.span.get_ref().is_none()); }); // Original thread can still see the contents. assert_eq!(err.span.get_ref().unwrap().index, 99); } ``` 4541