Rust
Future traiti
Future trait'inin poll mekanizmasını öğrenirsin.
Future trait'i
async fn'in arkasında tek metotlu bir trait vardır:
pub trait Future {
type Output;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
}
pub enum Poll<T> {
Ready(T),
Pending,
}
poll ya sonucu (Ready) döndürür ya da henüz hazır olmadığını (Pending) söyler. Pending dönen Future, hazır olduğunda cx.waker() ile yürütücüyü uyandırmayı taahhüt eder.
El yazımı Future
Birkaç kez Pending dönüp sonra hazır olan bir Future:
struct Geri {
kalan: u32,
}
impl Future for Geri {
type Output = &'static str;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
if self.kalan == 0 {
return Poll::Ready("bitti");
}
self.kalan -= 1;
cx.waker().wake_by_ref(); // "beni tekrar poll et"
Poll::Pending
}
}
Geri alanları Unpin olduğu için Pin<&mut Self> üzerinden alanlara doğrudan erişilebilir.
Uygulama Sayan yürütücü
Yukarıdaki Geri Future'ını yaz. block_on'u, sonucu ve kaç kez poll ettiğini birlikte döndüren calistir olarak değiştir. Geri { kalan: 3 } için ikisini boşlukla yazdır.
Örnek çözümü göster
use std::future::Future;
use std::pin::{pin, Pin};
use std::task::{Context, Poll, Waker};
struct Geri {
kalan: u32,
}
impl Future for Geri {
type Output = &'static str;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
if self.kalan == 0 {
return Poll::Ready("bitti");
}
self.kalan -= 1;
cx.waker().wake_by_ref();
Poll::Pending
}
}
fn calistir<F: Future>(f: F) -> (F::Output, u32) {
let mut f = pin!(f);
let mut cx = Context::from_waker(Waker::noop());
let mut sayi = 0;
loop {
sayi += 1;
if let Poll::Ready(v) = f.as_mut().poll(&mut cx) {
return (v, sayi);
}
}
}
fn main() {
let (sonuc, n) = calistir(Geri { kalan: 3 });
println!("{} {}", sonuc, n);
}
Kendini test et
-
Bir Future <code>Pending</code> döndürüp Waker'ı hiç çağırmazsa gerçek bir runtime'da ne olur?
- Runtime yeniden dener
- Panic
- Sonuç None olur
- Görev bir daha poll edilmez ve sonsuza dek takılır
Cevabı göster
Görev bir daha poll edilmez ve sonsuza dek takılır — Uyandırma sözleşmesi zorunludur; kendi Future'ını yazarken en sık yapılan hata budur.
-
Henüz hazır değil
self.kalan -= 1;
cx.waker().wake_by_ref();
Poll::____
Cevabı göster
self.kalan -= 1;
cx.waker().wake_by_ref();
Poll::Pending
-
Öğe ve görevi
- Poll::Ready(v)
- Sonuç hazır
- Poll::Pending
- Daha sonra
- cx.waker()
- Uyandırıcı
- type Output
- Sonuç türü
Sıradaki ders: async block