Структура Timer
Источник: Документация async-io::Timer
#![allow(unused)] fn main() { pub struct Timer { /* private fields */ } }
Фьючерс или поток, который эмитирует события по времени.
Описание
Таймеры - это фьючерсы, которые выводят единственный Instant при срабатывании.
Таймеры также являются потоками, которые могут периодически выводить Instant.
Точность
Существует ограничение на максимальную точность, которую может обеспечить Timer. Этот предел зависит от текущей платформы; например, в Windows максимальная точность составляет около 16 миллисекунд. Из-за этого ограничения таймер может спать дольше запрошенной длительности. Он никогда не будет спать меньше.
Примеры
Ожидание 1 секунды:
#![allow(unused)] fn main() { use async_io::Timer; use std::time::Duration; Timer::after(Duration::from_secs(1)).await; }
Таймаут через 1 секунду:
#![allow(unused)] fn main() { use async_io::Timer; use futures_lite::FutureExt; use std::time::Duration; let addrs = async_net::resolve("google.com:80") .or(async { Timer::after(Duration::from_secs(1)).await; Err(std::io::ErrorKind::TimedOut.into()) }) .await?; }
Методы
Создание таймеров
| Метод | Сигнатура | Описание |
|---|---|---|
never | pub fn never() -> Timer | Создает таймер, который никогда не сработает |
after | pub fn after(duration: Duration) -> Timer | Создает таймер, который сработает один раз через указанную длительность |
at | pub fn at(instant: Instant) -> Timer | Создает таймер, который сработает один раз в указанный момент времени |
interval | pub fn interval(period: Duration) -> Timer | Создает таймер, который срабатывает периодически |
interval_at | pub fn interval_at(start: Instant, period: Duration) -> Timer | Создает таймер, который срабатывает периодически, начиная с start |
Управление таймерами
| Метод | Сигнатура | Описание |
|---|---|---|
will_fire | pub fn will_fire(&self) -> bool | Показывает, сработает ли когда-либо этот таймер |
set_after | pub fn set_after(&mut self, duration: Duration) | Устанавливает таймер на срабатывание один раз через указанную длительность |
set_at | pub fn set_at(&mut self, instant: Instant) | Устанавливает таймер на срабатывание один раз в указанный момент |
set_interval | pub fn set_interval(&mut self, period: Duration) | Устанавливает таймер на периодическое срабатывание |
set_interval_at | pub fn set_interval_at(&mut self, start: Instant, period: Duration) | Устанавливает таймер на периодическое срабатывание, начиная с start |
Примеры использования
Таймер, который никогда не срабатывает
#![allow(unused)] fn main() { use async_io::Timer; use futures_lite::prelude::*; use std::time::Duration; async fn run_with_timeout(timeout: Option<Duration>) { let timer = timeout .map(|timeout| Timer::after(timeout)) .unwrap_or_else(Timer::never); run_lengthy_operation().or(timer).await; } // Таймаут через 5 секунд. run_with_timeout(Some(Duration::from_secs(5))).await; // Без таймаута. run_with_timeout(None).await; }
Интервальный таймер
#![allow(unused)] fn main() { use async_io::Timer; use futures_lite::StreamExt; use std::time::{Duration, Instant}; let period = Duration::from_secs(1); Timer::interval(period).next().await; }
Проверка срабатывания таймера
#![allow(unused)] fn main() { use async_io::Timer; use futures_lite::prelude::*; use std::time::Duration; // `never` никогда не сработает. assert!(!Timer::never().will_fire()); // `after` сработает, если длительность не слишком большая. assert!(Timer::after(Duration::from_secs(1)).will_fire()); assert!(!Timer::after(Duration::MAX).will_fire()); // Однако после срабатывания таймер `after` больше никогда не сработает. let mut t = Timer::after(Duration::from_secs(1)); assert!(t.will_fire()); (&mut t).await; assert!(!t.will_fire()); // Интервальные таймеры срабатывают периодически. let mut t = Timer::interval(Duration::from_secs(1)); assert!(t.will_fire()); t.next().await; assert!(t.will_fire()); }
Реализации трейтов
Future
Таймер реализует Future<Output = Instant>, что позволяет использовать его с await:
#![allow(unused)] fn main() { impl Future for Timer { type Output = Instant; fn poll(self: Pin<&mut Timer>, cx: &mut Context<'_>) -> Poll<Instant>; } }
Stream
Таймер также реализует Stream<Item = Instant> для периодического использования:
#![allow(unused)] fn main() { impl Stream for Timer { type Item = Instant; fn poll_next(self: Pin<&mut Timer>, cx: &mut Context<'_>) -> Poll<Option<Instant>>; fn size_hint(&self) -> (usize, Option<usize>); } }
Другие трейты
Debug- отладочное представлениеDrop- управление временем жизниSend,Sync- безопасность для многопоточностиUnpin- можно перемещать после закрепления
Особенности
- Переиспользование wake-ов: Методы
set_*не удаляют waker связанной задачи - Платформенные ограничения: Точность зависит от ОС
- Гибкость: Может использоваться как фьючерс и как поток