Pin
Async blocks and functions return types implementing the Future
trait. The type returned is the result of a compiler transformation which turns local variables into data stored inside the future.
Some of those variables can hold pointers to other local variables. Because of that, the future should never be moved to a different memory location, as it would invalidate those pointers.
To prevent moving the future type in memory, it can only be polled through a pinned pointer. Pin
is a wrapper around a reference that disallows all operations that would move the instance it points to into a different memory location.
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. -
Data that contains pointers to itself is called self-referential. Normally, the Rust borrow checker would prevent self-referential data from being moved, as the references cannot outlive the data they point to. However, the code transformation for async blocks and functions is not verified by the borrow checker.
-
Pin
is a wrapper around a reference. An object cannot be moved from its place using a pinned pointer. However, it can still be moved through an unpinned pointer. -
The
poll
method of theFuture
trait usesPin<&mut Self>
instead of&mut Self
to refer to the instance. That’s why it can only be called on a pinned pointer.