如何在 Rust 结构内创建线程局部变量? [英] How to create a thread local variable inside of a Rust struct?

查看:44
本文介绍了如何在 Rust 结构内创建线程局部变量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要一个线程局部变量,理想情况下存储在一个结构中,该结构当前存储了我程序的大部分全局状态.

I need a thread local variable, ideally stored in a struct which currently stores most of my program's global state.

我能看到的第一种方法是使用 thread_local! 宏,但是我想将此线程保持在我的状态结构中.

The first way I can see to do this is to use the thread_local! macro, however I would like to keep this thread local within my state struct.

我可以看到的第二种方法是在线程和线程局部变量的值之间使用 HashMap 或类似的方法.然后我会有一个使用 thread::current 来查找适当值的 getter.

The second way I can see to achieve this is to have a HashMap<Thread,MyThreadLocalData> or similar between threads and the value of my thread local variable(s). I would then have a getter which uses thread::current to lookup the appropriate value.

我应该提到的最后一个要求是,并非给定程序中的所有线程都是由 Rust 代码创建的,但 Rust 代码可以在任何线程上运行,因此解决方案应该对此具有鲁棒性.

One last requirement which I should mention is that not all threads in the given program are created by Rust code, but Rust code may be run on any thread, so solutions should be robust to this.

是否有这样做的最佳实践方法?也许有一个 threadId 可以让我使用简单的 Vec 而不是 HashMap (和/或避免散列开销)?有图书馆吗?

Is there a best practice way of doing this? Perhaps there is a threadId that would allow me to use a simple Vec instead of a HashMap (and/or avoid hashing overhead)? Is there a library for this?

另一种选择是修改可以在多线程上下文中使用的每个函数的参数,以获取状态结构和线程本地状态结构,但是这对于不是由 Rust 创建的线程来说并不容易.

Another option would be to modify the parameters of every function that could be used in a multithreaded context to take both a state struct and a threadlocal state struct, however this would not easily work with threads not created by Rust.

推荐答案

在结构中使用线程局部变量可以通过将它放在一个 impl 块中来完成:

Using a thread local variable in your struct can be done by placing it in an impl block:

use std::cell::RefCell;

struct Foo;
impl Foo {
    thread_local! {
        // Could add pub to make it public to whatever Foo already is public to.
        static FOO: RefCell<usize> = RefCell::new(0);
    }
}

并且可以使用 Foo::FOO 访问:

And is accessible using Foo::FOO:

Foo::FOO.with(|x| println!("{:?}", x));

游乐场
但是请注意,必须使用它前面的 Foo:: 来访问它,因为它不是一个字段,而是一个关联的 static.

Playground
Note, however, that accessing this must be done using Foo:: preceding it, since it's not a field, but instead an associated static.

也可以通过存储对它的引用来完成:

It could also be done by storing a reference to it:

use std::cell::RefCell;
use std::thread::LocalKey;

thread_local! {
    // Note lack of pub
    static FOO: RefCell<usize> = RefCell::new(0);
}
struct Bar {
    // Visibility here changes what can see `foo`.
    foo: &'static LocalKey<RefCell<usize>>,
    // Rest of your data.
}
impl Bar {
    fn constructor() -> Self {
        Self {
            foo: &FOO,
            // Rest of your data.
        }
    }
}

这篇关于如何在 Rust 结构内创建线程局部变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆