Skip to content

Instantly share code, notes, and snippets.

@ssrlive
Last active February 27, 2025 04:41
Show Gist options
  • Save ssrlive/729e19d303aed9ac67d8c3f55690973c to your computer and use it in GitHub Desktop.
Save ssrlive/729e19d303aed9ac67d8c3f55690973c to your computer and use it in GitHub Desktop.
learn async for rust
//
// cargo test mytest -- --nocapture
//
#[cfg(test)]
mod tests {
use std::{
future::Future,
pin::Pin,
task::{Context, Poll},
thread::sleep,
};
struct ReadFileFuture {
counter: usize,
}
impl Future for ReadFileFuture {
type Output = String;
fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
println!("ReadFileFuture::poll");
sleep(std::time::Duration::from_secs(1));
_cx.waker().wake_by_ref();
if self.counter > 5 {
return Poll::Ready("=== hello from file1 ===".to_string());
}
self.counter += 1;
Poll::Pending
}
}
#[tokio::test]
async fn mytest() {
println!("hello before reading");
let h1 = tokio::spawn(async {
println!("hello from h1");
let v = ReadFileFuture { counter: 0 }.await;
println!("out put from h1: {}", v);
});
let h2 = tokio::spawn(async {
println!("hello from h2");
let v = read_from_file2().await;
println!("out put from h2: {}", v);
});
let h3 = tokio::spawn(async {
println!("hello from h3");
AsyncTimer::new(std::time::Instant::now() + std::time::Duration::from_secs(2)).await;
println!("end h3");
});
let _ = tokio::join!(h1, h2, h3);
println!("end reading");
}
fn read_from_file2() -> impl Future<Output = String> {
async {
println!("read_from_file2");
sleep(std::time::Duration::from_secs(2));
"--- hello from file2 ---".to_string()
}
}
pub struct AsyncTimer {
expiration: std::time::Instant,
}
impl AsyncTimer {
pub fn new(expiration: std::time::Instant) -> Self {
AsyncTimer { expiration }
}
}
impl Future for AsyncTimer {
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
println!("AsyncTimer::poll");
if self.expiration <= std::time::Instant::now() {
Poll::Ready(())
} else {
let waker = cx.waker().clone();
let expiration = self.expiration;
std::thread::spawn(move || {
sleep(expiration - std::time::Instant::now());
waker.wake();
});
Poll::Pending
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment