如何实现从Futures 0.2中的另一个线程中唤醒的Future?

时间:2018-05-19 11:58:31

标签: asynchronous rust future

我试图找到一种简单的方法来实现未来包装箱{0.2}的Future特性:

extern crate futures;

use futures::executor::ThreadPool;
use futures::prelude::*;
use futures::task::Context;
use std::{thread, time::Duration};

struct SendThree {
    firstTime: bool,
}

impl Future for SendThree {
    type Item = u32;
    type Error = Never;

    fn poll(&mut self, ctx: &mut Context) -> Result<Async<Self::Item>, Never> {
        if self.firstTime {
            self.firstTime = false;
            thread::spawn(move || {
                thread::sleep(Duration::from_millis(10));
                ctx.waker().wake();
            });
            Ok(Async::Pending)
        } else {
            Ok(Async::Ready(3))
        }
    }
}

fn main() {
    let mut fut = SendThree { firstTime: true };
    let mut executor: ThreadPool = ThreadPool::new().unwrap();
    let result = executor.run(fut).unwrap();
    println!("{}", result);
}

playground

我的问题是Context变量不是Send所以我无法从另一个帖子调用wake

error[E0277]: the trait bound `futures::executor::Executor: std::marker::Send` is not satisfied
  --> src/main.rs:19:13
   |
19 |             thread::spawn(move || {
   |             ^^^^^^^^^^^^^ `futures::executor::Executor` cannot be sent between threads safely
   |
   = help: the trait `std::marker::Send` is not implemented for `futures::executor::Executor`
   = note: required because of the requirements on the impl of `std::marker::Send` for `&mut futures::executor::Executor`
   = note: required because it appears within the type `std::option::Option<&mut futures::executor::Executor>`
   = note: required because it appears within the type `futures::task::Context<'_>`
   = note: required because of the requirements on the impl of `std::marker::Send` for `&mut futures::task::Context<'_>`
   = note: required because it appears within the type `[closure@src/main.rs:19:27: 22:14 ctx:&mut futures::task::Context<'_>]`
   = note: required by `std::thread::spawn`

如果我将代码更改为此可行,但我无法阻止thread::sleep

if self.firstTime {
    self.firstTime = false;
    ctx.waker().wake();
    Ok(Async::Pending)
}

有没有惯用的方法来实现这个?

1 个答案:

答案 0 :(得分:0)

虽然Context无法跨线程发送,但Waker是:

fn poll(&mut self, ctx: &mut Context) -> Result<Async<Self::Item>, Never> {
    if self.first_time {
        self.first_time = false;
        let waker = ctx.waker().clone();
        thread::spawn(move || {
            thread::sleep(Duration::from_millis(10));
            waker.wake();
        });
        Ok(Async::Pending)
    } else {
        Ok(Async::Ready(3))
    }
}

请注意,这是一种实现超时的非常低效的方法。应该使用Futures-native方法。