Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Структура 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?;
}

Методы

Создание таймеров

МетодСигнатураОписание
neverpub fn never() -> TimerСоздает таймер, который никогда не сработает
afterpub fn after(duration: Duration) -> TimerСоздает таймер, который сработает один раз через указанную длительность
atpub fn at(instant: Instant) -> TimerСоздает таймер, который сработает один раз в указанный момент времени
intervalpub fn interval(period: Duration) -> TimerСоздает таймер, который срабатывает периодически
interval_atpub fn interval_at(start: Instant, period: Duration) -> TimerСоздает таймер, который срабатывает периодически, начиная с start

Управление таймерами

МетодСигнатураОписание
will_firepub fn will_fire(&self) -> boolПоказывает, сработает ли когда-либо этот таймер
set_afterpub fn set_after(&mut self, duration: Duration)Устанавливает таймер на срабатывание один раз через указанную длительность
set_atpub fn set_at(&mut self, instant: Instant)Устанавливает таймер на срабатывание один раз в указанный момент
set_intervalpub fn set_interval(&mut self, period: Duration)Устанавливает таймер на периодическое срабатывание
set_interval_atpub 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 связанной задачи
  • Платформенные ограничения: Точность зависит от ОС
  • Гибкость: Может использоваться как фьючерс и как поток