Трейт Future
Трейт Future описывает асинхронное значение, которое
будет доступно в будущем. Он лежит в основе всей
асинхронной экосистемы Rust. Тип, реализующий этот трейт,
представляет собой вычисление, которое может находиться
в одном из двух состояний: готово (значение доступно)
или ожидание (вычисление ещё не завершено).
Основным методом трейта является poll, который
принимает контекст задачи и возвращает перечисление
Poll. Параметром метод принимает ссылку на
контекст Context, содержащий Waker для
уведомления о готовности результата.
Синтаксис
pub trait Future {
type Output;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
}
Пример
Давайте создадим простейший тип, реализующий трейт
Future, который немедленно возвращает значение
"abcde":
use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};
struct MyFuture;
impl Future for MyFuture {
type Output = &'static str;
fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
Poll::Ready("abcde")
}
}
fn main()
{
let mut fut = MyFuture;
let mut cx = Context::from_waker(futures::task::noop_waker_ref());
let pinned = Pin::new(&mut fut);
let res = pinned.poll(&mut cx);
println!("{:?}", res);
}
Результат выполнения кода:
Ready("abcde")
Пример
Давайте рассмотрим пример, где футура возвращает значение после нескольких опросов, используя счётчик:
use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};
struct Countdown {
count: u32,
}
impl Future for Countdown {
type Output = u32;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
if self.count == 0 {
Poll::Ready(0)
} else {
self.count -= 1;
cx.waker().wake_by_ref();
Poll::Pending
}
}
}
fn main()
{
let mut fut = Countdown { count: 3 };
let mut cx = Context::from_waker(futures::task::noop_waker_ref());
let mut pinned = Pin::new(&mut fut);
loop {
match pinned.as_mut().poll(&mut cx) {
Poll::Ready(val) => {
println!("Ready: {}", val);
break;
}
Poll::Pending => {
println!("Pending");
}
}
}
}
Результат выполнения кода:
Pending
Pending
Pending
Ready: 0