[英]How to use Context and Wakers when implementing Future in practice
我發現很難理解為什么以及何時需要對傳遞給 object 上的poll
方法的Context
和/或其Waker
顯式執行某些操作,我正在為其實現Future
。 我一直在閱讀Tokio和Async Book的文檔,但我覺得示例/方法太抽象而無法應用於實際問題。
例如,我會認為下面的 MRE 會死鎖,因為new_inner_task
生成的未來不知道消息何時在 MPSC 通道上傳遞,但是,這個例子似乎工作正常。 為什么會這樣?
use std::{future::Future, pin::Pin, task::{Context, Poll}, time::Duration};
use futures::{FutureExt, StreamExt}; // 0.3
use tokio::sync::mpsc; // 1.2
use tokio_stream::wrappers::UnboundedReceiverStream; // 0.1
async fn new_inner_task(rx: mpsc::UnboundedReceiver<()>) {
let mut requests = UnboundedReceiverStream::new(rx);
while let Some(_) = requests.next().await {
eprintln!("received request");
}
}
pub struct ActiveObject(Pin<Box<dyn Future<Output = ()> + Send>>);
impl ActiveObject {
pub fn new() -> (Self, mpsc::UnboundedSender<()>) {
let (tx, rx) = mpsc::unbounded_channel();
(Self(new_inner_task(rx).boxed()), tx)
}
}
impl Future for ActiveObject {
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
eprintln!("[polled]");
self.get_mut().0.as_mut().poll(cx)
}
}
async fn delayed_send(delay: u64, sender: mpsc::UnboundedSender<()>) {
tokio::time::sleep(Duration::from_millis(delay)).await;
sender.send(()).unwrap();
eprintln!("sent request");
}
#[tokio::main]
async fn main() {
let (obj, tx) = ActiveObject::new();
let ds = delayed_send(500, tx.clone());
let ds2 = delayed_send(1000, tx);
tokio::join!(obj, ds, ds2);
}
我從本地運行此示例獲得的 output 是:
[polled]
[polled]
sent request
[polled]
received request
[polled]
sent request
[polled]
received request
因此,雖然我沒有對Context
或Waker
做任何事情,但ActiveObject
似乎以合理的速度被輪詢,也就是說,比要求的頻率更高,但不是忙於等待。 是什么導致ActiveObject
以這種速度被喚醒/輪詢?
您正在將相同的Context
(因此Waker
)傳遞給由new_inner_task
返回的 Future 的poll()
方法,該方法將其沿鏈傳遞到由UnboundedReceiverStream::next()
返回的Future
的poll()
) 。 其實現安排在適當的時間(當新元素出現在通道中時)在此Waker
上調用wake()
)。 完成后,Tokio 會輪詢與此Waker
關聯的頂級 future - 三個 future 的join!()
。
如果您省略了輪詢內部任務的行並只返回Poll::Pending
,您將得到預期的情況,您的Future
將被輪詢一次,然后永遠“掛起”,因為沒有什么會再次喚醒它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.