Как создать локальную переменную потока внутри структуры Rust? - PullRequest
0 голосов
/ 07 апреля 2020

Мне нужна локальная переменная потока, в идеале хранящаяся в структуре, которая в настоящее время хранит большую часть глобального состояния моей программы.

Первый способ сделать это - использовать макрос thread_local!, однако я хотел бы сохранить этот поток локальным в моей структуре состояний.

Второй способ, которым я могу видеть чтобы достичь этого, нужно иметь HashMap<Thread,MyThreadLocalData> или подобное между потоками и значением локальной переменной (переменных) моего потока. Затем я получу геттер, который использует thread::current для поиска подходящего значения.

Последнее требование, которое я должен упомянуть, состоит в том, что не все потоки в данной программе создаются кодом Rust, но код Rust может быть работать в любом потоке, поэтому решения должны быть устойчивыми к этому.

Есть ли лучший способ сделать это? Возможно, есть threadId, который позволил бы мне использовать простой Vec вместо HashMap (и / или избежать хэширования)? Есть ли библиотека для этого?

Другой вариант - изменить параметры каждой функции, которая может использоваться в многопоточном контексте, чтобы получить как структуру состояния, так и структуру состояния потока, однако это будет нелегко сработать. с темами, не созданными Rust.

1 Ответ

2 голосов
/ 07 апреля 2020

Использование локальной переменной потока в вашей структуре можно сделать, поместив ее в блок impl:

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:

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

Playground
Обратите внимание, однако, что доступ к этому должен быть сделан с использованием Foo:: перед ним, так как это не поле, а вместо связанного static.

Это также может быть сделано сохранив ссылку на него:

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.
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...