|
|
|
@ -109,7 +109,7 @@ async fn main() {
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
以上代码很清晰的解释了如何自定义一个 `Future`,并指定它如何通过 `poll` 一步一步执行,直到最终完成返回 "done" 字符串。
|
|
|
|
|
以上代码很清晰的解释了如何自定义一个 `Future`,并指定它如何通过 `poll` 一步一步执行,直到最终完成返回 `"done"` 字符串。
|
|
|
|
|
|
|
|
|
|
#### async fn 作为 Future
|
|
|
|
|
|
|
|
|
@ -247,7 +247,7 @@ impl MiniTokio {
|
|
|
|
|
|
|
|
|
|
鉴于此,我们的 mini-tokio 只应该在 `Future` 准备好可以进一步运行后,才去 `poll` 它,例如该 `Future` 之前阻塞等待的**资源**已经准备好并可以被使用了,就可以对其进行 `poll`。再比如,如果一个 `Future` 任务在阻塞等待从 TCP socket 中读取数据,那我们只想在 `socket` 中有数据可以读取后才去 `poll` 它,而不是没事就 `poll` 着玩。
|
|
|
|
|
|
|
|
|
|
回到在上面的代码中,mini-tokio 只应该当任务的延迟时间到了后,才去 `poll` 它。 为了实现这个功能,我们需要 `通知 -> 运行` 机制:当任务可以进一步被推进运行时,它会主动通知执行器,然后执行器再来 `poll`。
|
|
|
|
|
回到上面的代码中,mini-tokio 只应该当任务的延迟时间到了后,才去 `poll` 它。 为了实现这个功能,我们需要 `通知 -> 运行` 机制:当任务可以进一步被推进运行时,它会主动通知执行器,然后执行器再来 `poll`。
|
|
|
|
|
|
|
|
|
|
## Waker
|
|
|
|
|
|
|
|
|
@ -347,7 +347,7 @@ impl Future for Delay {
|
|
|
|
|
|
|
|
|
|
#### 处理 wake 通知
|
|
|
|
|
|
|
|
|
|
下面,让我们更新 mint-tokio 服务,让它能接受 wake 通知:当 `waker.wake()` 被调用后,相关联的任务会被放入执行器的队列中,然后等待执行器的调用执行。
|
|
|
|
|
下面,让我们更新 mint-tokio 服务,让它能接收 wake 通知:当 `waker.wake()` 被调用后,相关联的任务会被放入执行器的队列中,然后等待执行器的调用执行。
|
|
|
|
|
|
|
|
|
|
为了实现这一点,我们将使用消息通道来排队存储这些被唤醒并等待调度的任务。有一点需要注意,从消息通道接收消息的线程(执行器所在的线程)和发送消息的线程(唤醒任务时所在的线程)可能是不同的,因此消息( `Waker` )必须要实现 `Send`和 `Sync`,才能跨线程使用。
|
|
|
|
|
|
|
|
|
@ -416,7 +416,7 @@ impl ArcWake for Task {
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
当之前的计时器线程调用 `waker.wake()` 时,所在的任务会被推入到消息通道中。因此接下来,我们需要实现接受端的功能,然后 `MiniTokio::run()` 函数中执行该任务:
|
|
|
|
|
当之前的计时器线程调用 `waker.wake()` 时,所在的任务会被推入到消息通道中。因此接下来,我们需要实现接收端的功能,然后 `MiniTokio::run()` 函数中执行该任务:
|
|
|
|
|
|
|
|
|
|
```rust
|
|
|
|
|
impl MiniTokio {
|
|
|
|
|