| Crates.io | async-foundation |
| lib.rs | async-foundation |
| version | 0.2.1 |
| created_at | 2025-11-23 18:18:33.366564+00 |
| updated_at | 2025-11-23 18:26:15.062345+00 |
| description | Foundational async primitives for Rust - timers, networking, and common utilities |
| homepage | https://gitlab.com/Efimster/async-job |
| repository | https://gitlab.com/Efimster/async-job |
| max_upload_size | |
| id | 1946827 |
| size | 231,254 |
Foundational async primitives for Rust – lightweight timers, networking utilities, and common async building blocks designed for low overhead and predictable performance.
timer, net, and common utilities) rather than a full async runtime.futures and can be integrated into custom executors or existing ecosystems.async_foundation::timer)
Timer abstraction for scheduling waits with millisecond-level control.async_foundation::net)
TcpReadStream / TcpWriteStream thin async wrappers around non-async mio types, adding Future/AsyncRead/AsyncWrite behavior with minimal overhead compared to using mio directly.UdpSocket async wrapper over standard UDP sockets.async_foundation::common)
ReadyFuture and related state/observable types for composing async workflows.For a full API overview, see the crate docs once published on docs.rs.
use async_foundation::timer::timer::Timer;
use futures::executor::block_on;
use std::time::Duration;
let mut timer = Timer::new();
block_on(async {
// Wait for 100ms
timer.wait(Duration::from_millis(100)).await;
// Multiple concurrent timers
let t1 = timer.wait(Duration::from_millis(50));
let t2 = timer.wait(Duration::from_millis(100));
futures::join!(t1, t2);
});
use async_foundation::net::tcp_stream::TcpStream;
use futures::executor::block_on;
use futures::{AsyncReadExt, AsyncWriteExt};
use std::net::TcpListener;
use std::thread;
// Server side
let listener = TcpListener::bind("127.0.0.1:0").unwrap();
let addr = listener.local_addr().unwrap();
thread::spawn(move || {
if let Ok((stream, _)) = listener.accept() {
// Handle connection
}
});
// Client side
block_on(async {
let mut stream = TcpStream::connect(addr).unwrap();
// Write data
stream.write_all(b"Hello, world!").await.unwrap();
// Read data
let mut buf = [0u8; 1024];
let n = stream.read(&mut buf).await.unwrap();
});
use async_foundation::net::udp_socket::UdpSocket;
use futures::executor::block_on;
use std::net::SocketAddr;
block_on(async {
// Bind a UDP socket (non-blocking)
let socket = UdpSocket::bind("127.0.0.1:0").unwrap();
// Send data (non-blocking, can be used in async context)
let target: SocketAddr = "127.0.0.1:8080".parse().unwrap();
socket.send_to(b"Hello", target).unwrap();
// Receive data (non-blocking)
let mut buf = [0u8; 1024];
let (n, from) = socket.recv_from(&mut buf).unwrap();
// UdpSocket also implements AsyncRead/AsyncWrite for stream-like usage
});
use async_foundation::common::ready_future::ReadyFuture;
use futures::executor::block_on;
// Create a future that can be completed later
let future = ReadyFuture::new();
let future_clone = future.clone();
// Complete it from another context
future.complete(42);
// Await the result
let result = block_on(future_clone);
match result {
async_foundation::common::ready_future_state::ReadyFutureResult::Completed(value) => {
assert_eq!(value, 42);
}
_ => unreachable!(),
}
// Or create a pre-completed future
let completed = ReadyFuture::new_completed("done");
let result = block_on(completed);
use async_foundation::common::ready_observable::ReadyObservable;
use futures::executor::block_on;
let mut observable = ReadyObservable::default();
// Multiple tasks can wait for the observable to become ready
let wait1 = observable.wait();
let wait2 = observable.wait();
// Complete the observable (wakes all waiters)
observable.complete();
// Both futures will now resolve
block_on(async {
futures::join!(wait1, wait2);
});
This crate is designed for low overhead and predictable performance:
std::thread::sleep for async contexts, with lower overhead than heavyweight runtime timers. Optimized for handling many concurrent timers efficiently.mio with minimal overhead compared to direct mio usage, while providing a more ergonomic async API.This crate does not aim to replace full-featured async runtimes like Tokio, async-std, or smol. Instead, it targets a specific niche:
In practice:
std::thread::sleep or ad-hoc timer wheels, async-foundation:
tokio::time::sleep):
timer_state and timer_future_state).mio and standard sockets.Use async-foundation when you:
Use a full runtime (Tokio, async-std, etc.) when you:
Need batteries-included features (spawning, timers, I/O, synchronization, etc.) in a single crate.
Prefer convenience over having to stitch together lower-level components yourself.
This project is licensed under the MIT License. See LICENSE for details.