不为Future调用Waker是否可行?会阻塞其他Future执行吗?
关于未触发wake的Future是否阻塞其他任务的问题
首先是你实现的代码:
use std::future::Future; use std::pin::Pin; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; use std::task::{Context, Poll, Waker}; use arc_swap::ArcSwap; struct MyFuture { flag: Arc<AtomicBool>, waker: Arc<ArcSwap<Option<Waker>>>, } impl MyFuture { fn change(&self) { if let Some(waker) = &*self.waker.load_full() { waker.wake_by_ref(); } self.flag.store(true, Ordering::SeqCst); } } impl Future for MyFuture { type Output = Option<()>; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { let flag = self.flag.load(Ordering::SeqCst); if flag { Poll::Ready(Some(())) } else { self.waker.store(Some(cx.waker().clone()).into()); Poll::Pending } } }
不会阻塞其他Future的执行。
Rust的异步运行时采用协作式调度:当某个Future的poll方法返回Poll::Pending时,调度器会将这个任务从当前执行队列中移除,把线程资源让给其他就绪的任务。只有当该Future对应的waker被唤醒时,调度器才会将它重新加入执行队列,再次调用它的poll方法。
所以即便你的change()永远不被调用,这个MyFuture只会一直处于挂起状态,不会占用线程执行时间,其他Future依然能正常被调度执行。
另外提个代码里的潜在问题:每次poll时都会直接覆盖waker存储的内容,如果存在多个不同的waker(比如任务被调度到不同线程执行),之前的waker会被丢弃,可能导致后续唤醒失效。可以考虑检查当前存储的waker是否与当前cx的waker一致,不一致时再更新,避免不必要的覆盖。
内容的提问来源于stack exchange,提问作者silverwen
相关产品推荐
相关产品推荐

