美文网首页RUST编程
003Rust异步编程,Future trait介绍

003Rust异步编程,Future trait介绍

作者: 令狐壹冲 | 来源:发表于2020-06-08 22:22 被阅读0次

    Future介绍

    Future是Rust异步编程的核心,Rust异步编程基本都是围绕Future来展开。那么,什么是Future呢? 首先,我们来看下简化版的Future,如下:

    trait SimpleFuture {
    type Output;
    fn poll(&mut self, wake: fn()) -> Poll<Self::Output>;
    }

    enum Poll<T> {
    Ready(T),
    Pending,
    }

    executor Future的执行者,Future是具有的惰性的,并不会自己的执行,所以需要有一个执行者(executor)来执行Future。

    Poll枚举类型

    表示Future的两个状态:Ready为完成状态,Pengding为未完成状态。

    poll函数

    executor通过调用poll函数可以推进Future的状态。调用poll时,如果完成,返回Ready状态;如果未完成则返回pengding状态。当wake函数被调用后,会通知executor再次调用poll函数。

    wake函数

    当Future变成Ready状态后,wake函数会被调用,executor就知道哪个Future已经准备好了,然后调用poll函数。

    使用SimpleFuture

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

    enum Poll<T> {
    Ready(T),
    Pending,
    }

    trait SimpleFuture {
    type Output;
    //fn poll(&mut self, wake: fn()) -> Poll<Self::Output>;
    fn poll(&mut self, wake: u32) -> Poll<Self::Output>;
    }

    static mut FINISHED: bool = false;

    struct MySleeper {
    polls: u64,
    wake: u32,
    }

    impl MySleeper {
    fn new() -> Self {
    MySleeper {
    polls: 0,
    wake: 0,
    }
    }
    }

    impl SimpleFuture for MySleeper {
    type Output = ();
    fn poll(&mut self, wake: u32) -> Poll<()> {
    unsafe {
    if FINISHED {
    Poll::Ready(())
    } else {
    self.wake = wake;
    self.polls += 1;
    println!("not ready yet --> {}", self.polls);
    Poll::Pending
    }
    }
    }
    }
    struct MyReactor {
    wake: u32,
    handle: Option<thread::JoinHandle<()>>,
    }

    impl MyReactor {
    fn new() -> MyReactor {
    MyReactor {
    wake: 0,
    handle: None,
    }
    }

    fn add_wake(&mut self, wake: u32) {
        self.wake = wake;
    }
    
    fn check_status(&mut self) {
        if self.handle.is_none() {
            let _wake = self.wake;
            let handle = thread::spawn(|| loop {
                thread::sleep(Duration::from_secs(5));
                {//模拟执行wake函数
                    unsafe {
                        FINISHED = true;
                    }
                }
            });
    
            self.handle = Some(handle);
        }
    }
    

    }

    struct MyExecutor;

    impl MyExecutor {
    fn block_on<F: SimpleFuture>(mut my_future: F, wake: u32) {
    loop {
    match my_future.poll(wake) {
    Poll::Ready(_) => {
    println!("my future execute ok!");
    break;
    },
    Poll::Pending => {
    unsafe {
    while !FINISHED {//FINISHED为true表示为唤醒
    thread::sleep(Duration::from_secs(1));
    }
    }
    }
    }
    }
    }
    }

    fn main() {
    let mut reactor = MyReactor::new();
    let sleeper = MySleeper::new();
    let wake = sleeper.wake;
    reactor.add_wake(wake);
    reactor.check_status();
    MyExecutor::block_on(sleeper, wake);
    }

    SimpleFuture

    简化版的Future,实际上是一个状态机。

    MyExecutor

    用来执行SimpleFuture的相关动作。

    MyReactor

    用来检测条件是否就位,从而通知MyExecutor执行SimpleFuture。

    真正的Future trait

    真正的Future的定义如下:

    trait Future {
    type Output;
    fn poll(
    // Note the change from &mut self to Pin<&mut Self>:
    self: Pin<&mut Self>,
    // and the change from wake: fn() to cx: &mut Context<'_>:
    cx: &mut Context<'_>,
    ) -> Poll<Self::Output>;
    }

    真正的Future中,poll函数中self的类型变为了Pin<&mut Self>,第二个参数wake: fn()变为 &mut Context<'_>。

    第一个改变是因为,通过Pin可以创建不可移动的 Future。不可移动的对象可以在它们的字段之间存储指针,例如:

    struct MyFut { a: i32, ptr_to_a: *const i32 }

    第二个改变是因为,唤醒Future的时候,需要带一些数据,我们之前的只是wake函数无法满足需求。

    相关文章

      网友评论

        本文标题:003Rust异步编程,Future trait介绍

        本文链接:https://www.haomeiwen.com/subject/ypodtktx.html