Skip to content

Instantly share code, notes, and snippets.

@muratamuu
Last active March 15, 2025 15:41
Show Gist options
  • Save muratamuu/102e704f646c1792f703054ce87c160e to your computer and use it in GitHub Desktop.
Save muratamuu/102e704f646c1792f703054ce87c160e to your computer and use it in GitHub Desktop.
Rust で非同期タイマー処理

tokio の例

準備

[dependencies]
tokio = { version = "1.23.0", features = ["time", "macros", "rt-multi-thread"] }

または

[dependencies]
tokio = { version = "1.23.0", features = ["full"] }

サンプルコード

#[tokio::main]
async fn main() {
    let mut timer = tokio::time::interval(std::time::Duration::from_secs(1));
    
    loop {
        timer.tick().await;
	println!("Hello world!");
    }
}

async_std の例

準備

async_std::stream::interval を使用するためには async-std の features にunstableフラグが必要。                                                                                                                                                                                                                                                            

[dependencies]
async-std = { version = "1.12.0", features = ["attributes", "unstable"] }

サンプルコード

#[async_std::main]
async fn main() {
    use async_std::stream::StreamExt; // for next() method

    let mut timer = async_std::stream::interval(std::time::Duration::from_secs(1));

    loop {
        timer.next().await;
        println!("Hello world!");
    }
}

futures の例

準備

[dependencies]
futures = "0.3.25"

サンプルコード

use std::time::{Instant, Duration};
use std::pin::Pin;
use std::task::{Context, Poll};
use std::thread;
use futures::stream::{Stream, StreamExt};

struct Interval {
    when: Option<Instant>,
    interval: Duration,
}

impl Interval {
    fn new(interval: Duration) -> Self {
        Self {
            when: None,
            interval: interval,
        }
    }
}

impl Stream for Interval {
    type Item = ();

    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
        if self.when.is_none() {
            self.when = Some(Instant::now() + self.interval);
        }
        let when = self.when.unwrap();
        if Instant::now() >= when {
            self.when = Some(when + self.interval);
            Poll::Ready(Some(()))
        } else {
            let waker = cx.waker().clone();
            thread::spawn(move || {
                let now = Instant::now();
                if now < when {
                    thread::sleep(when - now);
                }
                waker.wake();
            });
            Poll::Pending
        }
    }
}

fn main() {

    let mut interval = Interval::new(Duration::from_secs(1));

    futures::executor::block_on(async {
        loop {
            interval.next().await;
            println!("Hello world!");
        }
    });
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment