Pin
Асинхронні блоки та функції повертають типи, що реалізують трейт Future
. Тип, що повертається, є результатом трансформації компілятора, який перетворює локальні змінні на дані, що зберігаються у ф’ючерсі.
Деякі з цих змінних можуть містити вказівники на інші локальні змінні. Через це ф’ючерс ніколи не слід переміщувати в іншу комірку пам’яті, оскільки це зробить ці вказівники недійсними.
Щоб запобігти переміщенню ф’ючерсного типу у пам’яті, його можна опитувати лише через закріплений вказівник. Закріплення - це обгортка навколо посилання, яка забороняє всі операції, що можуть перемістити екземпляр, на який воно вказує, в іншу ділянку пам’яті.
Speaker Notes
This slide should take about 20 minutes.
-
Ви можете розпізнати це як приклад шаблону актора. Актори зазвичай викликають
select!
у циклі. -
Це є підсумком кількох попередніх уроків, тож не поспішайте з цим.
-
Наївно додайте
_ = sleep(Duration::from_millis(100)) => { println!(..) }
доselect!
. Це ніколи не буде виконано. Чому? -
Замість цього додайте
timeout_fut
, що містить цей ф’юсчерс за межамиloop
: -
Це все ще не працює. Слідкуйте за помилками компілятора, додавши
&mut
доtimeout_fut
уselect!
, щоб обійти переміщення, а потім використовуючиBox::pin
: -
Це компілюється, але після закінчення часу очікування на кожній ітерації відображається
Poll::Ready
(злитий ф’ючерс міг би допомогти в цьому). Оновіть, щоб скидатиtimeout_fut
кожного разу, коли він спливає:
-
-
Box виділяє у купі. У деяких випадках,
std::pin::pin!
(лише нещодавно стабілізовано, у старому коді часто використовуєтьсяtokio::pin!
) також є варіантом, але його важко використовувати для фьючерсів, які перепризначено. -
Інша альтернатива — взагалі не використовувати
pin
, а створювати інше завдання, яке буде надсилати на каналoneshot
кожні 100 мс. -
Дані, які містять вказівники на себе, називаються самопосилальними. Зазвичай, перевірка запозичень у Rust запобігає переміщенню самопосилань, оскільки посилання не можуть пережити дані, на які вони вказують. Однак, перетворення коду для асинхронних блоків і функцій не перевіряється перевіркою запозичень.
-
Pin
- це обгортка навколо вказівника. Об’єкт не можна перемістити з його місця за допомогою закріпленого вказівника. Однак, його можна переміщати за допомогою незакріпленого вказівника. -
Метод
poll
трейтуFuture
використовуєPin<&mut Self>
замість&mut Self
для посилання на екземпляр. Тому його можна викликати лише на закріпленому покажчику.