async-foundation 0.2.1

Foundational async primitives for Rust - timers, networking, and common utilities
Documentation
## async-foundation

Foundational async primitives for Rust – lightweight timers, networking utilities, and common async building blocks designed for low overhead and predictable performance.

### What this crate is

- **Focused building blocks**: Provides a small, well-defined set of primitives (`timer`, `net`, and `common` utilities) rather than a full async runtime.
- **Runtime-agnostic**: Works with standard `futures` and can be integrated into custom executors or existing ecosystems.
- **Performance-oriented**: Comes with a comprehensive Criterion benchmark suite for timers, networking, and internal data structures.

### Core components

- **Timers (`async_foundation::timer`)**
  - High-level `Timer` abstraction for scheduling waits with millisecond-level control.
  - Designed to handle both single-shot and many concurrent timers efficiently.
- **Networking (`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.
- **Common utilities (`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.

### Examples

#### Timer

```rust
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);
});
```

#### TCP Networking

```rust
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();
});
```

#### UDP Networking

```rust
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
});
```

#### ReadyFuture

```rust
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);
```

#### ReadyObservable

```rust
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);
});
```

### Performance characteristics

This crate is designed for **low overhead and predictable performance**:

- **Timers**: More efficient than `std::thread::sleep` for async contexts, with lower overhead than heavyweight runtime timers. Optimized for handling many concurrent timers efficiently.
- **Networking**: Thin wrappers around `mio` with minimal overhead compared to direct `mio` usage, while providing a more ergonomic async API.
- **Memory**: Low allocation overhead for timers and networking primitives, making it suitable for high-throughput scenarios.

### How this compares to other solutions

This crate does **not** aim to replace full-featured async runtimes like Tokio, async-std, or smol. Instead, it targets a specific niche:

- **You want lower-level control** over timers and I/O than high-level runtimes typically expose.
- **You want small, composable primitives** that can be wired into your own executor or integrated into existing systems.
- **You care about predictable overhead** and want benchmarks baked into the project so you can reason about performance over time.

In practice:

- Compared to **using `std::thread::sleep` or ad-hoc timer wheels**, `async-foundation`:
  - Provides low-overhead timer creation with explicit, benchmarked behavior for concurrent and sequential timers.
- Compared to **using only high-level runtime timers (e.g. `tokio::time::sleep`)**:
  - This crate gives you more **visibility into timer internals** (via `timer_state` and `timer_future_state`).
  - It is easier to embed in minimal or experimental executors where you don’t want to pull in a full runtime.
- For **networking**, the focus is on:
  - Providing **thin, benchmarked wrappers** around `mio` and standard sockets.
  - Making it straightforward to measure and reason about the overhead of stream/socket wrappers and timeout handling.

Use `async-foundation` when you:

- Are building your own async runtime or executor.
- Need fine-grained control over timers and timeouts.
- Want a small, well-benchmarked layer for async networking primitives without a heavyweight dependency tree.

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.


### License

This project is licensed under the MIT License. See `LICENSE` for details.