Fijar

Cuando esperas un futuro, todas las variables locales (que normalmente se almacenarían en un marco de pila) se almacenan en el futuro del bloque asíncrono. Si tu futuro tiene punteros en datos de la pila, podrían invalidarse. Es una acción insegura.

Por lo tanto, debes asegurarte de que las direcciones a las que apunta el futuro no cambien. Por ese motivo debemos fijar (pin) los futuros. Si se usa el mismo futuro varias veces en un select!, se suelen producir problemas en los valores fijados.

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Speaker Notes

  • Puede que reconozcas esto como un ejemplo del patrón actor. Los actores suelen llamar a select! en un bucle.

  • Esta sección es un resumen de algunas de las lecciones anteriores, así que tómate tu tiempo .

    • Si añade un _ = sleep(Duration::from_millis(100)) => { println!(..) } a select!, nunca se ejecutará. ¿Por qué?

    • En su lugar, añade un timeout_fut que contenga ese futuro fuera de loop:

      #![allow(unused)] fn main() { let mut timeout_fut = sleep(Duration::from_millis(100)); loop { select! { .., _ = timeout_fut => { println!(..); }, } } }
    • Continuará sin funcionar. Sigue los errores del compilador y añade &mut a timeout_fut en select! para ir despejando el problema. A continuación, usa Box::pin:

      #![allow(unused)] fn main() { let mut timeout_fut = Box::pin(sleep(Duration::from_millis(100))); loop { select! { .., _ = &mut timeout_fut => { println!(..); }, } } }
    • Se puede compilar, pero una vez que vence el tiempo de espera, aparece Poll::Ready en cada iteración (un futuro fusionado podría resultar útil). Actualiza para restablecer timeout_fut cada vez que expire.

  • Box se asigna en el montículo. En algunos casos, std::pin::pin! (solo si se ha estabilizado recientemente, con código antiguo que suele utilizar tokio::pin!) también es una opción, pero difícil de utilizar en un futuro que se reasigna.

  • Otra alternativa es no utilizar pin, sino generar otra tarea que se enviará a un canal de oneshot cada 100 ms.