2 unstable releases

0.2.1 Mar 6, 2025
0.2.0 Mar 1, 2025
0.1.0 Feb 19, 2025

#1486 in Asynchronous

Download history 131/week @ 2025-02-17 129/week @ 2025-02-24 174/week @ 2025-03-03 12/week @ 2025-03-10

446 downloads per month

MIT/Apache

130KB
2.5K SLoC

GitHub Actions Workflow Status docs.rs Crates.io Version

local-runtime

Thread-local async runtime

This crate provides an async runtime that runs entirely within the current thread. As such, it can run futures that are !Send and non-static. If no future is able to make progress, the runtime will suspend the current thread until a future is ready to be polled.

In addition, This crate provides async timers and an async adapter for standard I/O types, similar to async-io.

Note: Currently, Windows is not supported.

See the docs for more info.


lib.rs:

Thread-local async runtime

This crate provides an async runtime that runs entirely within the current thread. As such, it can run futures that are !Send and non-static. If no future is able to make progress, the runtime will suspend the current thread until a future is ready to be polled.

To actually run a future, see block_on or Executor::block_on, which drives the future to completion on the current thread.

In addition, This crate provides async timers and an async adapter for standard I/O types, similar to async-io.

Implementation

Task wakeups are handled by a thread-local reactor, which keeps track of all I/O events and timers in the current thread along with their associated wakers. Waiting for the reactor is done by block_on, without needing a separate thread.

The implementation of the reactor depends on the platform. On Unix systems, the reactor uses poll. Currently, Windows is not supported.

Concurrency

The Executor can spawn tasks that run concurrently on the same thread. Alternatively, this crate provides macros such as join and merge_futures for concurrent execution.

Compatibility

Unlike other runtimes, local_runtime doesn't run the reactor in the background, instead relying on block_on to run the reactor while polling the future. Since leaf futures from this crate, such as Async and timers, rely on the reactor to wake up, they can only be driven by block_on, and are not compatible with other runtimes.

Examples

Listen for connections on a local port, while concurrently making connections to localhost. Return with error if any operation fails.

use std::{net::{TcpStream, TcpListener}, time::Duration, io};
use futures_lite::{AsyncReadExt, AsyncWriteExt, StreamExt};
use local_runtime::{io::Async, time::sleep, Executor};

let ex = Executor::new();
ex.block_on(async {
    let listener = Async::<TcpListener>::bind(([127, 0, 0, 1], 0))?;
    let addr = listener.get_ref().local_addr()?;

    // Run this task in the background
    let _bg = ex.spawn(async move {
        // Listen for connections on local port
        loop {
            let (mut stream, _) = listener.accept().await?;
            let mut buf = [0u8; 5];
            stream.read_exact(&mut buf).await?;
            assert_eq!(&buf, b"hello");
        }
        Ok::<_, io::Error>(())
    });

    // Connect to the listener repeatedly with 50us delay
    loop {
        let mut stream = Async::<TcpStream>::connect(addr).await?;
        stream.write_all(b"hello").await?;
        sleep(Duration::from_micros(500)).await;
    }
    Ok::<_, io::Error>(())
})?;

Dependencies

~2–11MB
~137K SLoC