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函数无法满足需求。
网友评论