Многопоточное взаимодействие с внешним процессом в Rust - PullRequest
1 голос
/ 29 октября 2019

Ржавый новичок здесь.

Я хотел бы запустить внешний длительный процесс и поговорить с ним по каналам из нескольких потоков в Rust.

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

Рассмотрим следующий пример:

use std::process::{Command, Stdio, ChildStdin};
use std::sync::Mutex;
use std::io::{Write};
use std::thread;

struct Element {
    sink: Mutex<Option<ChildStdin>>
}

impl Element {
    fn launch_process(&self) {
        let child =
            Command::new("sed").args(&["s/foo/bar/g"])
                .stdin(Stdio::piped())
                .spawn()
                .unwrap();

        let mut sink = self.sink.lock().unwrap();
        *sink = child.stdin;
    }

    fn tx(&self, content: &[u8]) {
        let mut sink = self.sink.lock().unwrap();
        sink.as_mut().unwrap().write(content);
    }

    fn start_tx(&self) {
        thread::spawn( || {
            self.tx(b"foo fighters");
        });
    }
}

fn main() {
    let e = Element {
        sink: Mutex::new(None)
    };

    e.launch_process();
    e.start_tx();
}

Если я удаляю бит thread::spawn, тогда все работает как положено. С thread::spawn на месте я получаю ошибку:

error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
  --> src/main.rs:28:24
   |
28 |           thread::spawn( || {
   |  ________________________^
29 | |             self.tx(b"foo fighters");
30 | |         });
   | |_________^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 27:5...
  --> src/main.rs:27:5
   |
27 | /     fn start_tx(&self) {
28 | |         thread::spawn( || {
29 | |             self.tx(b"foo fighters");
30 | |         });
31 | |     }
   | |_____^
   = note: ...so that the types are compatible:
           expected &&Element
              found &&Element
   = note: but, the lifetime must be valid for the static lifetime...
note: ...so that the type `[closure@src/main.rs:28:24: 30:10 self:&&Element]` will meet its required lifetime bounds
  --> src/main.rs:28:9
   |
28 |         thread::spawn( || {
   |         ^^^^^^^^^^^^^

error: aborting due to previous error

1 Ответ

1 голос
/ 01 ноября 2019

Вы не можете передать &self (временное заимствование) потоку, поскольку поток может продолжать работать после того, как ссылка больше не действительна.

Для использования данных из потоков у вас есть только два варианта:

  • Дайте право собственности (что является исключительным) объекту потоку, то есть используйте закрытие move ||, и не пытайтесь впоследствии использовать этот объект из основного потока, илилюбой другой поток.

  • Оберните объект в Arc, чтобы получить совместное владение потокобезопасным, и отправьте клон в поток (с Arc::clone это дешево, и лежащие в основе данныеshared).

Когда компилятор говорит, что вам нужно «статическое время жизни», игнорируйте это. Для всех практических целей это означает, что «ссылки не допускаются».

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