J'essaie de créer une structure qui permettra à quelqu'un d'appeler .shutdown()
, ce qui résoudra un avenir (qui est par ailleurs en attente). Il ne peut être appelé qu'une seule fois. Dans l'implémentation du trait Future
, je reçois une erreur indiquant que poll
n'est pas défini, bien qu'il soit présent dans la documentation (sous impl Future
).
Bien que j'utilise std::future::Future
comme impl
, j'ai essayé d'ajouter use futures::prelude::*
, ce qui mettrait le trait d'aperçu dans la portée. RLS et rustc m'informent que l'importation n'est pas utilisée, donc ce n'est pas le problème.
Notez que je n'utilise pas un simple drapeau booléen, car j'ai l'intention que cela puisse être appelé à partir de n'importe quel thread - c'est un détail d'implémentation qui est non pertinent ici.
use futures::channel::oneshot; // [email protected]
use std::{
future::Future,
pin::Pin,
task::{Context, Poll},
};
pub struct ShutdownHandle {
sender: oneshot::Sender<()>,
receiver: oneshot::Receiver<()>,
}
impl ShutdownHandle {
pub fn new() -> Self {
let (sender, receiver) = oneshot::channel();
Self { sender, receiver }
}
pub fn shutdown(self) -> Result<(), ()> {
self.sender.send(())
}
}
impl Future for ShutdownHandle {
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
self.receiver.poll(&mut cx).map(|_| ())
}
}
fn main() {
let runner = ShutdownHandle::new();
assert!(runner.shutdown().is_ok());
}
Je reçois l'erreur suivante:
error[E0599]: no method named `poll` found for type `futures_channel::oneshot::Receiver<()>` in the current scope
--> src/main.rs:28:23
|
28 | self.receiver.poll(&mut cx).map(|_| ())
| ^^^^
Qu'est-ce que je rate? Il y a sûrement un moyen de "passer" le scrutin. J'utilise tous les soirs (2019-07-18).
C'est vrai, Receiver
n'implémente pas Future
; uniquement Pin<&mut Receiver>
le fait. Vous devez projet l'épinglage de votre type sur le terrain.
Unpin
impl Future for ShutdownHandle {
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
// I copied this code from Stack Overflow without reading the text that
// told me how to verify that this code uses `unsafe` correctly.
unsafe { self.map_unchecked_mut(|s| &mut s.receiver) }.poll(cx).map(|_| ())
}
}
Vous devez lire le module pin
pour bien comprendre la configuration requise pour utiliser unsafe
ici.
J'aime utiliser une bibliothèque d'aide, telle que pin_project , pour gérer des types de projection plus compliqués:
#[unsafe_project(Unpin)]
pub struct ShutdownHandle {
#[pin]
sender: oneshot::Sender<()>,
#[pin]
receiver: oneshot::Receiver<()>,
}
impl Future for ShutdownHandle {
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
let this = self.project();
this.receiver.poll(cx).map(|_| ())
}
}
Unpin
Ömer Erden souligne que la caisse d'aperçu à terme fournit FutureExt::poll_unpin
. Cette méthode prend une référence mutable à un type qui implémente Unpin
et crée un tout nouveau Pin
avec.
Puisque oneshot::Receiver
implémente Unpin
, ceci peut être utilisé ici:
impl Future for ShutdownHandle {
type Output = ();
fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
self.receiver.poll_unpin(cx).map(|_| ())
}
}