Улучшение Rust's Future, чтобы не создавать отдельный поток - PullRequest
0 голосов
/ 01 ноября 2018

Я написал простое будущее на основе этого учебника , который выглядит следующим образом:

extern crate chrono; // 0.4.6
extern crate futures; // 0.1.25

use std::{io, thread};
use chrono::{DateTime, Duration, Utc};
use futures::{Async, Future, Poll, task};

pub struct WaitInAnotherThread {
    end_time: DateTime<Utc>,
    running: bool,
}

impl WaitInAnotherThread {
    pub fn new(how_long: Duration) -> WaitInAnotherThread {
        WaitInAnotherThread {
            end_time: Utc::now() + how_long,
            running: false,
        }
    }

    pub fn run(&mut self, task: task::Task) {
        let lend = self.end_time;

        thread::spawn(move || {
            while Utc::now() < lend {
                let delta_sec = lend.timestamp() - Utc::now().timestamp();
                if delta_sec > 0 {
                    thread::sleep(::std::time::Duration::from_secs(delta_sec as u64));
                }
                task.notify();
            }
            println!("the time has come == {:?}!", lend);
        });
    }
}

impl Future for WaitInAnotherThread {
    type Item = ();
    type Error = Box<io::Error>;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        if Utc::now() < self.end_time {
            println!("not ready yet! parking the task.");

            if !self.running {
                println!("side thread not running! starting now!");
                self.run(task::current());
                self.running = true;
            }

            Ok(Async::NotReady)
        } else {
            println!("ready! the task will complete.");
            Ok(Async::Ready(()))
        }
    }
}

Таким образом, вопрос заключается в том, как заменить pub fn run(&mut self, task: task::Task) чем-то, что не создаст новый поток для решения в будущем. Было бы полезно, если бы кто-то мог переписать мой код с замененной функцией run без отдельного потока, это поможет мне понять, как все должно быть. Также я знаю, что у tokio есть реализация тайм-аута, но мне нужен этот код для изучения.

1 Ответ

0 голосов
/ 01 ноября 2018

Мне кажется, я понимаю, что вы имеете в виду. Допустим, у вас есть две задачи: основная и рабочая1, в этом случае вы опрашиваете рабочий1, чтобы дождаться ответа; НО есть лучший способ, и это ждать соревнования Worker1; и это может быть сделано без какого-либо будущего, вы просто вызываете из Main функцию Worker1, когда рабочий по окончании Main продолжится. Вам не нужно будущее, вы просто вызываете функцию, а разделение Main и Worker1 - просто чрезмерное усложнение.

Теперь, я думаю, ваш вопрос стал актуальным в тот момент, когда вы добавили хотя бы другого работника, в последний раз добавили Worker2, и вы хотите, чтобы Main возобновил вычисления, как только одна из двух задач будет выполнена; и вы не хотите, чтобы эта задача выполнялась в другом потоке / процессе, возможно, из-за того, что вы используете асинхронный вызов (что просто означает, что потоки выполняются где-то еще, или вы достаточно низкого уровня, чтобы получить аппаратное прерывание).

Поскольку ваши Worker1 и Worker2 должны совместно использовать один и тот же поток, вам нужен способ сохранить текущее выполнение Main, создать один для одного из работников, а после определенного объема работы, времени или другого даже (Планировщик) переключиться на другого работника и так далее. Это многозадачная система, и для нее есть различные программные реализации в Rust; но с поддержкой HW вы могли бы делать то, что в программном обеспечении вы не могли делать (например, аппаратное обеспечение не позволяло одной Задаче получить доступ к ресурсу из другой), плюс вы можете заставить ЦП заботиться о переключении задач и все ... Ну, вот что такое Thread и Process.

Будущее - это не то, что вы ищете, это более высокий уровень, и вы можете найти какой-нибудь программный планировщик, который их поддерживает.

...