在rust异步函数中,没有任何方法可以访问当前的Context,而无需编写Future
的显式实现?
在实际回答问题之前,记住Context
是什么很有用;每当编写依赖外部资源(例如I / O)的Future
的实现时,您都不想忙于等待任何事情。结果,您很可能具有Future
的实现,将在其中返回Pending
,然后将其唤醒。为此存在Context
(和Waker
)。
但是,这就是它们:低级实施细节。如果您已经在使用Future
而不是编写低级实现,则Waker
很可能包含在[[somewhere中,但您无法直接访问。
Waker
占实施细节泄漏的时间为99.9%,实际上不建议这样做。但是,将Waker
用作bigger
struct
的一部分是完全可以的,但这是您需要从头开始实现自己的Future
的地方。 没有其他有效的用例,按照常规,您永远不需要直接访问Waker
。由于操场的局限性,令人遗憾的是我无法向您展示一个生动的例子,说明何时获得此Waker
很有用;但是,将来可能会在这种情况下使用这种设置:假设我们正在建造房屋的前门。我们有一个门铃和一扇门,当有人敲门铃时我们希望得到通知。但是,我们不想在门口等候访客。因此,我们创建了两个对象:FrontDoor
和Doorbell
,并且我们将wire()
的选项赋予Doorbell
以连接这两个对象。
pub struct FrontDoor {
doorbell: Arc<RwLock<Doorbell>>
}
impl FrontDoor {
pub fn new() -> FrontDoor {
FrontDoor {
doorbell: Arc::new(RwLock::new(Doorbell {
waker: None,
visitor: false
}))
}
}
pub fn wire(&self) -> Arc<RwLock<Doorbell>> {
self.doorbell.clone() // We retrieve the bell
}
}
impl Future for FrontDoor {
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
self.doorbell.read().map(|guard| {
match guard.visitor {
true => Poll::Ready(()),
false => Poll::Pending
}
}).unwrap_or(Poll::Pending)
}
}
pub struct Doorbell {
waker: Option<Waker>,
pub visitor: bool
}
impl Doorbell {
pub fn ring(&mut self) {
self.visitor = true;
self.waker.as_ref().map(|waker| waker.wake_by_ref());
}
}
我们的FrontDoor
实现了Future
,这意味着我们可以将其扔给您选择的执行程序;waker
包含在Doorbell
对象中,它使我们能够“振铃”并唤醒我们的未来。