在Rust中,如何访问外部线程局部全局变量?

9
以下是每种线程本地存储实现方式,使用标准ffi机制和编译器或标准库提供的方法,如何在Rust程序中访问外部线程本地变量?
  • C11
  • gcc的tls扩展
  • pthreads
  • Windows TLS API

2
你能否补充这个库并提供一个C函数来读写那些thread_local变量? - kennytm
是的。如果Rust缺乏必要的功能来处理线程本地变量,我的意图是编写一个小型粘合库来处理它们。然而,如果有可能,我更喜欢避免额外的构建依赖。 - Doe
2
任何答案都需要您告诉我们使用的线程系统以及如何创建线程本地变量。一个很好的方法是提供一个 [MCVE],其中包含外部代码和您创建的 Rust 代码,展示您想要访问它的方式。 - Shepmaster
1
如果线程本地变量被声明为pub,则应该能够从任何地方访问它。请参见LocalKeythread_local,或者查看playground - rnstlr
1
@Doe 哦,我误解了。我添加了一个使用gcc的C11 _Thread_local解决方案的答案。 - rnstlr
显示剩余2条评论
1个回答

8
Rust有一个夜间特性,允许链接到外部线程本地变量。该特性的稳定性可以在此处进行跟踪。
C11定义了_Thread_local关键字来定义对象的线程存储期。还存在thread_local宏别名。
GCC还实现了Thread Local扩展,使用__thread作为关键字。

使用nightly版本(已测试rustc 1.17.0-nightly (0e7727795 2017-02-19)和gcc 5.4),可以链接到外部C11 _Thread_local和gcc __thread变量。

#![feature(thread_local)]

extern crate libc;

use libc::c_int;

#[link(name="test", kind="static")]
extern {
    #[thread_local]
    static mut test_global: c_int;
}

fn main() {
    let mut threads = vec![];
    for _ in 0..5 {
        let thread = std::thread::spawn(|| {
            unsafe {
                test_global += 1;
                println!("{}", test_global);
                test_global += 1;
            }
        });
        threads.push(thread);
    }

    for thread in threads {
        thread.join().unwrap();
    }
}

这使得可以访问声明为以下任一类型的变量:
_Thread_local extern int test_global;
extern __local int test_global;

以上 Rust 代码的输出将是:
1
1
1
1
1

当变量被定义为线程本地时,这是可以预期的。

1
优秀的回答。相应的跟踪问题似乎是 https://github.com/rust-lang/rust/issues/29594。从问题中看来,稳定化似乎不太可能。 - Doe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接