Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/glandium/os-thread-local
OS-backed thread-local storage for rust
https://github.com/glandium/os-thread-local
Last synced: about 2 months ago
JSON representation
OS-backed thread-local storage for rust
- Host: GitHub
- URL: https://github.com/glandium/os-thread-local
- Owner: glandium
- License: apache-2.0
- Created: 2019-10-25T00:55:17.000Z (about 5 years ago)
- Default Branch: master
- Last Pushed: 2021-02-01T10:13:26.000Z (almost 4 years ago)
- Last Synced: 2024-10-11T01:54:39.364Z (3 months ago)
- Language: Rust
- Homepage:
- Size: 22.5 KB
- Stars: 7
- Watchers: 3
- Forks: 4
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- License: LICENSE-APACHE
Awesome Lists containing this project
README
# OS-backed thread-local storage
This crate provides a `ThreadLocal` type as an alternative to
`std::thread_local!` that allows per-object thread-local storage, while
providing a similar API. It always uses the thread-local storage primitives
provided by the OS.On Unix systems, pthread-based thread-local storage is used.
On Windows, fiber-local storage is used. This acts like thread-local
storage when fibers are unused, but also provides per-fiber values
after fibers are created with e.g. `winapi::um::winbase::CreateFiber`.The [`thread_local`](https://crates.io/crates/thread_local) crate is an example
of another crate that provides per-object thread-local storage, with a
different API, and different features, but with more performance overhead than
this one.# Examples
This is the same as the example in the [`std::thread::LocalKey`] documentation,
but adjusted to use `ThreadLocal` instead. To use it in a `static` context, a
lazy initializer, such as [`once_cell::sync::Lazy`] or [`lazy_static!`] is
required.[`std::thread::LocalKey`]: https://doc.rust-lang.org/std/thread/struct.LocalKey.html
[`once_cell::sync::Lazy`]: https://docs.rs/once_cell/1.2.0/once_cell/sync/struct.Lazy.html
[`lazy_static!`]: https://docs.rs/lazy_static/1.4.0/lazy_static/```rust
use std::cell::RefCell;
use std::thread;
use once_cell::sync::Lazy;
use os_thread_local::ThreadLocal;static FOO: Lazy>> =
Lazy::new(|| ThreadLocal::new(|| RefCell::new(1)));FOO.with(|f| {
assert_eq!(*f.borrow(), 1);
*f.borrow_mut() = 2;
});// each thread starts out with the initial value of 1
let t = thread::spawn(move || {
FOO.with(|f| {
assert_eq!(*f.borrow(), 1);
*f.borrow_mut() = 3;
});
});// wait for the thread to complete and bail out on panic
t.join().unwrap();// we retain our original value of 2 despite the child thread
FOO.with(|f| {
assert_eq!(*f.borrow(), 2);
});
```A variation of the same with scoped threads and per-object thread-local
storage:```rust
use std::cell::RefCell;
use crossbeam_utils::thread::scope;
use os_thread_local::ThreadLocal;struct Foo {
data: u32,
tls: ThreadLocal>,
}let foo = Foo {
data: 0,
tls: ThreadLocal::new(|| RefCell::new(1)),
};foo.tls.with(|f| {
assert_eq!(*f.borrow(), 1);
*f.borrow_mut() = 2;
});scope(|s| {
// each thread starts out with the initial value of 1
let foo2 = &foo;
let t = s.spawn(move |_| {
foo2.tls.with(|f| {
assert_eq!(*f.borrow(), 1);
*f.borrow_mut() = 3;
});
});// wait for the thread to complete and bail out on panic
t.join().unwrap();// we retain our original value of 2 despite the child thread
foo.tls.with(|f| {
assert_eq!(*f.borrow(), 2);
});
}).unwrap();
```