Rust 異步編程,Future trait 介紹

Future介紹

Future是Rust異步編程的核心,Rust異步編程基本都是圍繞Future來展開。那麼,什麼是Future呢? 首先,我們來看下簡化版的Future,如下:

```

trait SimpleFuture {

type Output;

fn poll(&mut self, wake: fn()) -> Poll;

}

enum Poll {

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 {

Ready(T),

Pending,

}

trait SimpleFuture {

type Output;

//fn poll(&mut self, wake: fn()) -> Poll;

fn poll(&mut self, wake: u32) -> Poll;

}

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>,

}

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(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`:

self: Pin,

// and the change from `wake: fn()` to `cx: &mut Context`:

cx: &mut Context,

) -> Poll;

}

```

真正的Future中,poll函數中self的類型變為了Pin,第二個參數wake: fn()變為 &mut Context。

第一個改變是因為,通過Pin可以創建不可移動的 Future。不可移動的對象可以在它們的字段之間存儲指針,例如:

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

第二個改變是因為,喚醒Future的時候,需要帶一些數據,我們之前的只是wake函數無法滿足需求。


分享到:


相關文章: