Как создать менеджер потоков? - PullRequest
1 голос
/ 10 октября 2019

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

На земле C ++ я бы создал класс, который абстрагирует всеэтого прочьУ него будет метод start, который инициализирует поток данных и запускает поток для обработки. У него был бы метод stop, который останавливает обработку и присоединяет поток.

Однако это не совсем Rusty и даже не работает в Rust.

Пример ( Детская площадка )

use std::thread;
use std::time::Duration;

struct Handler {
    worker_handle: Option<thread::JoinHandle<()>>,
    stop_flag: bool, // Should be atomic, but lazy for example
}

impl Handler {

    pub fn new() -> Handler {
        let worker_handle = None;
        let stop_flag = true;

        return Handler { worker_handle, stop_flag };
    }

    pub fn start(&mut self) {
        self.stop_flag = false;
        self.worker_handle = Some(std::thread::spawn(move || {
            println!("Spawned");
            self.worker_fn();
        }));
    }

    pub fn stop(&mut self) {
        let handle = match self.worker_handle {
            None => return,
            Some(x) => x,
        };
        self.stop_flag = true;
        handle.join();
    }

    fn worker_fn(&mut self) {
        while !self.stop_flag {
            println!("Working!");
        }
    }
}

fn main() {
    let mut handler = Handler::new();
    handler.start();
    thread::sleep(Duration::from_millis(10000));
    handler.stop();
}

Вывод:

error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
  --> src/main.rs:20:54
   |
20 |           self.worker_handle = Some(std::thread::spawn(move || {
   |  ______________________________________________________^
21 | |             println!("Spawned");
22 | |             self.worker_fn();
23 | |         }));
   | |_________^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 18:5...
  --> src/main.rs:18:5
   |
18 | /     pub fn start(&mut self) {
19 | |         self.stop_flag = false;
20 | |         self.worker_handle = Some(std::thread::spawn(move || {
21 | |             println!("Spawned");
22 | |             self.worker_fn();
23 | |         }));
24 | |     }
   | |_____^
   = note: ...so that the types are compatible:
           expected &mut Handler
              found &mut Handler
   = note: but, the lifetime must be valid for the static lifetime...
note: ...so that the type `[closure@src/main.rs:20:54: 23:10 self:&mut Handler]` will meet its required lifetime bounds
  --> src/main.rs:20:35
   |
20 |         self.worker_handle = Some(std::thread::spawn(move || {
   |                                   ^^^^^^^^^^^^^^^^^^

error: aborting due to previous error

Даже если я обманываю и удаляю вызов worker_fn, я все равно не могу работать с JoinHandle как и можно ожидать от земли C ++.

error[E0507]: cannot move out of `self.worker_handle.0` which is behind a mutable reference
  --> src/main.rs:27:28
   |
27 |         let handle = match self.worker_handle {
   |                            ^^^^^^^^^^^^^^^^^^ help: consider borrowing here: `&self.worker_handle`
28 |             None => return,
29 |             Some(x) => x,
   |                  -
   |                  |
   |                  data moved here
   |                  move occurs because `x` has type `std::thread::JoinHandle<()>`, which does not implement the `Copy` trait

error: aborting due to previous error

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

Но я все еще хочу создать некоторый интерфейс, который позволит мне просто раскрутить поток данных, не беспокоясь об управлении потоками, и я не совсем уверен, что лучший способ сделать это.

Похоже, у меня есть две основные проблемы.

1) Как создать функцию, которая будет выполняться в потоке, который принимает данные из внешнего источника и может сигнализировать о безопасном выходе? Если бы у меня был атомный бул для его уничтожения, как бы я поделился этим между потоками?

2) Как мне справиться с присоединением потока, когда я закончу? Метод stop должен очистить поток, но я не знаю, как отследить ссылку на него.

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