#thread-local-storage #os #primitive #storage-api #lazy-evaluation #per-object #os-backed

os-thread-local

基于 OS 的线程本地存储。此软件包提供了一个 ThreadLocal 类型,作为 std::thread_local! 的替代方案,允许按对象进行线程本地存储,同时提供类似的 API。它始终使用由操作系统提供的线程本地存储原语。

4 个版本

0.1.3 2019 年 12 月 19 日
0.1.2 2019 年 10 月 25 日
0.1.1 2019 年 10 月 25 日
0.1.0 2019 年 10 月 25 日

1100Rust 模式

Download history 14689/week @ 2024-03-25 13029/week @ 2024-04-01 11681/week @ 2024-04-08 12904/week @ 2024-04-15 12967/week @ 2024-04-22 13114/week @ 2024-04-29 13161/week @ 2024-05-06 13202/week @ 2024-05-13 13291/week @ 2024-05-20 13168/week @ 2024-05-27 14992/week @ 2024-06-03 16174/week @ 2024-06-10 14842/week @ 2024-06-17 12882/week @ 2024-06-24 15115/week @ 2024-07-01 16576/week @ 2024-07-08

61,952 每月下载量
4 软件包中使用 (直接使用 3 个)

Apache-2.0/MIT

27KB
390

基于 OS 的线程本地存储

此软件包提供了一个 ThreadLocal 类型,作为 std::thread_local! 的替代方案,允许按对象进行线程本地存储,同时提供类似的 API。它始终使用由操作系统提供的线程本地存储原语。

在 Unix 系统上,使用基于 pthread 的线程本地存储。

在 Windows 上,使用纤维本地存储。当纤维未被使用时,它类似于线程本地存储,但在创建纤维后(例如,使用 winapi::um::winbase::CreateFiber)还提供按纤维的值。

thread_local 软件包是另一个提供按对象线程本地存储的软件包的示例,具有不同的 API 和不同的功能,但与这个软件包相比,性能开销更大。

示例

这与 std::thread::LocalKey 文档中的示例相同,但已调整以使用 ThreadLocal。要在 static 上下文中使用它,需要懒加载初始化器,例如 once_cell::sync::Lazylazy_static!

use std::cell::RefCell;
use std::thread;
use once_cell::sync::Lazy;
use os_thread_local::ThreadLocal;

static FOO: Lazy<ThreadLocal<RefCell<u32>>> =
    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);
});

具有范围线程和按对象线程本地存储的相同示例的变体

use std::cell::RefCell;
use crossbeam_utils::thread::scope;
use os_thread_local::ThreadLocal;

struct Foo {
    data: u32,
    tls: ThreadLocal<RefCell<u32>>,
}

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();

依赖项

~215KB