Future trait
定义:
pub trait Future {
type Output;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
}
MiniTokio
主要由三部分组成:
结构体定义:包含一个
Receiver
,用于从channel
中接收Task
;一个Sender
,用于分发给Task
pub struct MiniTokio {
// 从通道中读取数据
receiver: Receiver<Arc<Task>>,
// 把句柄分发给 Task,让它们能把自身发送到通道里
sender: Sender<Arc<Task>>,
}
new()
函数:创建通道,创建MiniTokio
实例spawn()
方法:调用Task
的spawn()
方法,把拿到的future
实例和Sender
引用发给Task
pub fn spawn<F>(&self, future: F)
where
F: Future<Output = ()> + Send + 'static,{
}
run()
方法:从channel
中取Task
,然后调用其poll()
方法、pub fn run(&self) {
}
Task
主要由四部分组成:
结构体定义:保存了一个
future
和一个Sender
对象pub struct Task {
future: Mutex<Pin<Box<dyn Future<Output = ()> + Send + 'static>>>,
sender: Sender<Arc<Task>>,
}
spawn
方法定义:用于生成Task
的实例,并将自身发送到channel
中pub fn spawn<F>(future: F, sender: &Sender<Arc<Task>>)
where
F: Future<Output = ()> + Send + 'static, {
}
poll()
方法定义:用于调用自身future
中的poll()
方法pub fn poll(self: &Arc<Task>) {
}
实现
ArcWake trait
:可以使用let waker = task::waker(self.clone());
,创建Waker
实例impl ArcWake for Task {
fn wake_by_ref(arc_self: &Arc<Self>) {
}
}
Task的类型
Arc<Task>
:
因为Task
是需要把自身发送到通道里的,所以需要有clone()
方法,因此使用Arc<T>
进行包装:
Future的类型
Mutex<Pin<Box<dyn Future<Output = ()> + Send>>>
:
Rust
允许Future
可以先后被多个**Task**
调度,属于多线程的访问,因此需要Sync trait
,因此使用Mutex<T>
进行包装Future
需要Pin
到堆上,因此需要使用Box::Pin
包装Future
类型的trait object
:Future<Output = ()> + Send
重点:
async
标记在异步函数前面,调用这个函数会返回一个**future**
异步操作是惰性的,只调用异步函数什么都不会发生,需要一个
caller
去调用这个future
的poll()
方法async
在编译时根据await
的调用被转换成状态机,状态机作为最外层的**future**
也实现了Future trait
,执行异步操作的过程就是层层向里执行poll()
方法的过程如果当前操作未完成,则返回
**Poll::Pending**
,并把当前传进来的Waker
记录下来Waker
是和Task
相关联的,它被包装进Context
中,传递给具体执行IO
操作的函数(Reactor
)当
I/O
操作完成之后,由Reactor
调用waker.wake()
函数,将Task
重新交给执行器executor
执行器
executor
再次调度这个Task
中的future
,推进状态此时资源是就绪状态,返回
**Poll::Ready()**