Прежде чем ответить на вопрос, полезно вспомнить, что такое Context
;всякий раз, когда вы пишете реализацию Future
, которая зависит от внешних ресурсов (скажем, ввода-вывода), вы не хотите ничего занятого ждать. В результате у вас, скорее всего, будут реализации Future
, где вы вернете Pending
, а затем разбудите его. Context
(и Waker
) существуют для этой цели.
Однако это то, чем они являются: низкоуровневые, подробности реализации. Если вы уже используете Future
в отличие от написания низкоуровневой реализации, то, скорее всего, Waker
будет содержаться где-то , но не будет напрямую доступно для вас.
В результате этого утечка Waker
напрямую является утечкой деталей реализации в 99,9% случаев и фактически не рекомендуется. Однако, Waker
, используемый как часть большего struct
, прекрасно работает, но именно здесь вам нужно будет реализовать свой собственный Future
с нуля. Нет другого действительного варианта использования для этого , и в обычных условиях вам никогда не потребуется прямой доступ к Waker
.
Из-за ограничений игровой площадки я, к сожалению, не могупокажу вам живой пример того, когда полезно получить это Waker
;однако, такая будущая установка может использоваться в такой ситуации: давайте предположим, что мы строим входную дверь дома. У нас есть дверной звонок и дверь, и мы хотим получать уведомления, когда кто-то звонит в дверь. Однако мы не хотим ждать посетителей у входа.
Поэтому мы создаем два объекта: FrontDoor
и Doorbell
, и мы даем возможность wire()
the 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
и позволяет нам «звонить» и пробуждать наше будущее.