改进Rust的未来,不创建单独的线程

时间:2018-11-01 07:15:21

标签: rust rust-tokio

我已经根据以下tutorial编写了一个简单的未来:

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 :(得分:0)

我想我明白你的意思。 假设您有两个任务,Main和Worker1,在这种情况下,您正在轮询worker1以等待答案。但是有更好的方法,这是等待Worker1的竞争。而且这可以在没有任何Future的情况下完成,您只需从Main调用Worker1函数,当工作进程结束时Main会继续运行。您不需要未来,只需要调用一个函数,Main和Worker1的除法就是一个过度复杂的过程。

现在,我认为您的问题在您至少添加了另一个工作程序,最后添加了Worker2的那一刻就变得很重要了,并且您希望Main在两个任务之一完成后立即恢复计算。并且您不希望这些任务在另一个线程/进程中执行,可能是因为您正在使用异步调用(这仅意味着线程在其他地方完成,或者您的级别足够低,您会收到硬件中断)。

由于您的Worker1和Worker2必须共享同一线程,因此您需要一种保存当前执行Main的方法,为其中一个worker创建一个,并在经过一定量的工作,时间甚至是其他时间之后(Scheduler) ,切换到其他工作人员,依此类推。这是一个多任务系统,Rust中有多种软件实现。但是在硬件支持下,您可以做只有软件才能做的事情(例如让硬件阻止一个任务从另一个任务访问资源),另外还可以让CPU负责任务切换以及所有任务...嗯,这就是线程和进程。

未来并不是您想要的,它们是更高层次的,您可以找到一些支持它们的软件调度程序。