Future trait

定义:

  1. pub trait Future {
  2. type Output;
  3. fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
  4. }

MiniTokio

主要由三部分组成:

  1. 结构体定义:包含一个Receiver,用于从channel中接收Task;一个Sender,用于分发给Task

    1. pub struct MiniTokio {
    2. // 从通道中读取数据
    3. receiver: Receiver<Arc<Task>>,
    4. // 把句柄分发给 Task,让它们能把自身发送到通道里
    5. sender: Sender<Arc<Task>>,
    6. }
  2. new()函数:创建通道,创建MiniTokio实例

  3. spawn()方法:调用Taskspawn()方法,把拿到的future实例和Sender引用发给Task

    1. pub fn spawn<F>(&self, future: F)
    2. where
    3. F: Future<Output = ()> + Send + 'static,{
    4. }
  4. run()方法:从channel中取Task,然后调用其poll()方法、

    1. pub fn run(&self) {
    2. }

Task

主要由四部分组成:

  1. 结构体定义:保存了一个future和一个Sender对象

    1. pub struct Task {
    2. future: Mutex<Pin<Box<dyn Future<Output = ()> + Send + 'static>>>,
    3. sender: Sender<Arc<Task>>,
    4. }
  2. spawn方法定义:用于生成Task的实例,并将自身发送到channel

    1. pub fn spawn<F>(future: F, sender: &Sender<Arc<Task>>)
    2. where
    3. F: Future<Output = ()> + Send + 'static, {
    4. }
  3. poll()方法定义:用于调用自身future中的poll()方法

    1. pub fn poll(self: &Arc<Task>) {
    2. }
  4. 实现ArcWake trait:可以使用let waker = task::waker(self.clone());,创建Waker实例

    1. impl ArcWake for Task {
    2. fn wake_by_ref(arc_self: &Arc<Self>) {
    3. }
    4. }

Task的类型

Arc<Task>
因为Task是需要把自身发送到通道里的,所以需要有clone()方法,因此使用Arc<T>进行包装:

Future的类型

Mutex<Pin<Box<dyn Future<Output = ()> + Send>>>

  1. Rust允许Future可以先后被多个**Task**调度,属于多线程的访问,因此需要Sync trait,因此使用Mutex<T>进行包装
  2. Future需要Pin到堆上,因此需要使用Box::Pin包装
  3. Future类型的trait objectFuture<Output = ()> + Send

重点:

  1. async标记在异步函数前面,调用这个函数会返回一个**future**

  2. 异步操作是惰性的,只调用异步函数什么都不会发生,需要一个caller去调用这个futurepoll()方法

  3. async在编译时根据await的调用被转换成状态机,状态机作为最外层的**future**也实现了Future trait,执行异步操作的过程就是层层向里执行poll()方法的过程

  4. 如果当前操作未完成,则返回**Poll::Pending**,并把当前传进来的Waker记录下来

  5. Waker是和Task相关联的,它被包装进Context中,传递给具体执行IO操作的函数(Reactor

  6. I/O操作完成之后,由Reactor调用waker.wake()函数,将Task重新交给执行器executor

  7. 执行器executor再次调度这个Task中的future,推进状态

  8. 此时资源是就绪状态,返回**Poll::Ready()**