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.
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!(..) }
aselect!
, nunca se ejecutará. ¿Por qué? -
En su lugar, añade un
timeout_fut
que contenga ese futuro fuera deloop
: -
Continuará sin funcionar. Sigue los errores del compilador y añade
&mut
atimeout_fut
enselect!
para ir despejando el problema. A continuación, usaBox::pin
: -
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 restablecertimeout_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 utilizartokio::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 deoneshot
cada 100 ms.