Как передать PrimInt нескольким потокам? - PullRequest
1 голос
/ 20 июня 2019

Я хотел бы написать функцию, которая принимает целое число и порождает потоки, которые используют это целое число. Целое число может быть вычислено. Это не должно быть буквальным. Если я использую конкретный тип, такой как usize, он будет работать, но когда я пытаюсь его обобщить, он не может скомпилировать :

fn g<A>(a: A)
where
    A: num::PrimInt + Copy + std::fmt::Debug + Send,
{
    let hs = (0..3).map(|_| {
        std::thread::spawn(move || {
            println!("{:?}", a);
        })
    });

    for h in hs {
        h.join().unwrap();
    }
}

Ошибка:

1 | fn g<A>(a: A)
  |      - help: consider adding an explicit lifetime bound `A: 'static`...
...
6 |         std::thread::spawn(move || {
  |         ^^^^^^^^^^^^^^^^^^
  |
note: ...so that the type `[closure@src/main.rs:6:28: 8:10 a:A]` will meet its required lifetime bounds
 --> src/main.rs:6:9
  |
6 |         std::thread::spawn(move || {
  |         ^^^^^^^^^^^^^^^^^^

Так как у меня есть черта Copy, она должна быть в состоянии скопировать это значение для каждого потока, и, следовательно, рекомендации по ограничению времени жизни не нужны. Как мне решить эту проблему?

Ответы [ 3 ]

1 голос
/ 21 июня 2019

Другие объяснили почему ваш код не работает, но если вам все еще интересно, как заставить его работать, просто добавьте + 'static к вашим ограничениям:

fn g<A>(a: A)
where
    A: num::PrimInt + Copy + std::fmt::Debug + Send + 'static,
{
    let hs = (0..3).map(|_| {
        std::thread::spawn(move || {
            println!("{:?}", a);
        })
    });

    for h in hs {
        h.join().unwrap();
    }
}
1 голос
/ 21 июня 2019

Copy и 'static - это разные ограничения, а и необходимы для перемещения значения по потокам.В то время как вы можете только намереваться передавать целые числа (которые удовлетворяют как Copy, так и 'static) вашей обобщенной функции, компилятор не может знать наверняка.Должно быть в состоянии доказать, что тело функции действительно для всех возможных параметров типа.Примером типа Copy, но не 'static является ссылка на локальную переменную :

fn assert_is_copy<T: Copy>(_: T) {}
fn assert_is_static<T: 'static>(_: T) {}

fn main() {
    let x: usize = 5;

    assert_is_copy(x);
    assert_is_static(x);
    assert_is_copy(&x);
    //assert_is_static(&x); // FAILS TO COMPILE
}

Я думаю, вы согласитесь, что вы не хотитепередавать ссылки на ваши переменные стека в разные потоки (хотя это может быть безопасно в в некоторых ограниченных случаях ).Если вы это сделали, вы можете отсоединить этот поток, вставить кадр стека с локальной переменной и вызвать неопределенное поведение!

Этот ответ дает простое (в основном) правильное объяснениечто значит сказать T: 'static.

0 голосов
/ 21 июня 2019

Прямой ответ на мой вопрос, основанный на других ответах, следующий:

В Rust невозможно передать вычисленное, не-литеральное PrimInt более чем в один поток.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...