This library provides a ThreadLocal
type which provides an alternative
to std::thread_local!
that always uses the thread-local storage
primitives provided by the OS, and allows per-object thread-local storage,
while providing a similar API.
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
crate also provides
per-object thread-local storage, with a different API, and different features,
but with more performance overhead than this one.
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.
```rust use std::cell::RefCell; use std::thread; use oncecell::sync::Lazy; use osthread_local::ThreadLocal;
static FOO: Lazy
FOO.with(|f| { asserteq!(*f.borrow(), 1); *f.borrowmut() = 2; });
// each thread starts out with the initial value of 1 let t = thread::spawn(move || { FOO.with(|f| { asserteq!(*f.borrow(), 1); *f.borrowmut() = 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 crossbeamutils::thread::scope; use osthread_local::ThreadLocal;
struct Foo {
data: u32,
tls: ThreadLocal
let foo = Foo { data: 0, tls: ThreadLocal::new(|| RefCell::new(1)), };
foo.tls.with(|f| { asserteq!(*f.borrow(), 1); *f.borrowmut() = 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| { asserteq!(*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(); ```