portable_async_sleep

Crates.ioportable_async_sleep
lib.rsportable_async_sleep
version0.1.1
created_at2025-06-09 04:45:59.603407+00
updated_at2025-08-29 04:43:02.276524+00
descriptionA portable async sleep function for Rust
homepagehttps://sealedabstract.com/code/portable_async_sleep
repositoryhttps://github.com/drewcrawford/portable_async_sleep
max_upload_size
id1705498
size126,496
Drew Crawford (drewcrawford)

documentation

README

portable-async-sleep

logo

A portable async sleep function for Rust.

This crate provides a runtime-agnostic implementation of async sleep functionality. Unlike runtime-specific sleep functions (e.g., tokio::time::sleep or async_std::task::sleep), portable_async_sleep works with any async runtime or executor.

Features

  • Runtime-agnostic: Works with tokio, async-std, smol, or any other async runtime
  • Lightweight: Uses standard library primitives with minimal overhead
  • Thread-safe: Can be used from multiple async tasks simultaneously
  • Accurate timing: Respects the requested sleep duration

Implementation

The default implementation uses a dedicated background thread that manages sleep timers using standard library channels and timeouts. This approach ensures maximum compatibility across all async runtimes while maintaining good performance.

While the stdlib-based implementation is the most portable, the crate is designed to support alternative backends in the future that may offer better performance or integration with specific runtimes, while still maintaining the same portable API.

Examples

Basic usage:

use portable_async_sleep::async_sleep;
use std::time::Duration;

async fn example() {
    async_sleep(Duration::from_millis(100)).await;
    println!("Slept for 100ms!");
}

Measuring sleep accuracy:

use portable_async_sleep::async_sleep;
use std::time::Duration;
#[cfg(not(target_arch = "wasm32"))]
use std::time::Instant;
#[cfg(target_arch = "wasm32")]
use web_time::Instant;

async fn accuracy_example() {
    let duration = Duration::from_millis(100);
    let start = Instant::now();

    async_sleep(duration).await;

    let elapsed = start.elapsed();
    assert!(elapsed >= duration);
    println!("Requested: {:?}, Actual: {:?}", duration, elapsed);
}

Using with concurrent tasks:

use portable_async_sleep::async_sleep;
use std::time::Duration;
#[cfg(not(target_arch = "wasm32"))]
use std::time::Instant;
#[cfg(target_arch = "wasm32")]
use web_time::Instant;

async fn concurrent_example() {
    let start = Instant::now();

    // Start two sleep operations concurrently
    let sleep1 = async_sleep(Duration::from_millis(100));
    let sleep2 = async_sleep(Duration::from_millis(200));

    // Wait for both to complete
    futures::join!(sleep1, sleep2);

    // Total time should be ~200ms, not 300ms
    let elapsed = start.elapsed();
    assert!(elapsed >= Duration::from_millis(200));
    assert!(elapsed < Duration::from_millis(250));
}

Multiple concurrent sleeps:

use portable_async_sleep::async_sleep;
use std::time::Duration;
#[cfg(not(target_arch = "wasm32"))]
use std::time::Instant;
#[cfg(target_arch = "wasm32")]
use web_time::Instant;

async fn multiple_concurrent_example() {
    // Multiple concurrent sleeps complete in parallel, not sequentially
    let start = Instant::now();

    let futures = vec![
        async_sleep(Duration::from_millis(100)),
        async_sleep(Duration::from_millis(100)),
        async_sleep(Duration::from_millis(100)),
    ];

    futures::future::join_all(futures).await;

    // Total time should be ~100ms, not 300ms
    let elapsed = start.elapsed();
    assert!(elapsed < Duration::from_millis(150));
}

License

This project is licensed under either of

at your option.

Commit count: 22

cargo fmt