switchy_async 0.2.0

Switchy Async runtime package
Documentation
# MoosicBox Async

Async runtime abstraction and utilities for MoosicBox applications.

## Overview

The MoosicBox Async package provides:

- **Runtime Abstraction**: Generic async runtime interface
- **Multi-Backend**: Support for Tokio and simulation runtimes
- **Builder Pattern**: Flexible runtime configuration
- **Feature-Gated**: Modular async functionality
- **Thread Management**: Thread ID tracking and management

## Features

### Runtime Abstraction

- **GenericRuntime**: Common interface for all async runtimes
- **Runtime Builder**: Configurable runtime construction
- **Backend Selection**: Choose between Tokio and simulation runtimes
- **Future Support**: Standard Future trait integration

### Backend Support

- **Tokio**: Production async runtime
- **Simulator**: Deterministic simulation runtime for testing
- **Feature-Gated**: Enable only needed backends

### Async Utilities

- **Thread ID**: Unique thread identification
- **Task Management**: Task spawning and joining
- **IO Operations**: Async I/O primitives (feature-gated)
- **Synchronization**: Async synchronization primitives (feature-gated)
- **Timers**: Async timing utilities (feature-gated)

## Installation

Add this to your `Cargo.toml`:

```toml
[dependencies]
switchy_async = "0.1.4"
```

With Tokio backend features:

```toml
[dependencies]
switchy_async = { version = "0.1.4", default-features = false, features = ["tokio", "rt-multi-thread", "io", "sync", "time", "macros"] }
```

For testing with simulation:

```toml
[dependencies]
switchy_async = { version = "0.1.4", default-features = false, features = ["simulator", "macros"] }
```

## Usage

### Runtime Creation

```rust
use switchy_async::{Builder, GenericRuntime};

// Create runtime with default settings (current-thread)
let runtime = Builder::new().build()?;

// Use generic runtime interface
runtime.block_on(async {
    println!("Hello from async runtime!");
});

// Wait for runtime to complete
runtime.wait()?;

// With multi-threaded runtime (requires rt-multi-thread feature)
#[cfg(feature = "rt-multi-thread")]
{
    let runtime = Builder::new()
        .max_blocking_threads(Some(4))
        .build()?;
    runtime.block_on(async {
        println!("Hello from multi-threaded runtime!");
    });
    runtime.wait()?;
}
```

### Backend-Specific Usage

```rust
// Tokio backend (when tokio feature enabled)
#[cfg(all(feature = "tokio", feature = "time", not(feature = "simulator")))]
use switchy_async::{Builder, task, time};

#[cfg(all(feature = "tokio", feature = "time", not(feature = "simulator")))]
{
    let runtime = Builder::new().build()?;

    // Spawn tasks
    runtime.block_on(async {
        let handle = task::spawn(async {
            time::sleep(time::Duration::from_millis(100)).await;
            "Task completed"
        });

        let result = handle.await.expect("task should complete");
        println!("{}", result);
    });

    runtime.wait()?;
}

// Additional modules available with features
#[cfg(feature = "io")]
use switchy_async::io;  // Async I/O traits and utilities

#[cfg(feature = "sync")]
use switchy_async::sync;  // Synchronization primitives

#[cfg(feature = "util")]
use switchy_async::util;  // Additional utilities
```

### Simulation Backend

```rust
// Simulation backend (when simulator feature enabled)
#[cfg(feature = "simulator")]
use switchy_async::simulator;

#[cfg(feature = "simulator")]
{
    let runtime = Builder::new().build()?;

    runtime.block_on(async {
        // Deterministic async execution for testing
        println!("Simulation runtime");
    });
}
```

### Thread Management

```rust
use switchy_async::thread_id;

// Get unique thread ID
let id = thread_id();
println!("Current thread ID: {}", id);
```

### Macros and Utilities

```rust
// Async macros (requires macros feature)
#[cfg(feature = "macros")]
use switchy_async::{select, join, try_join};

#[cfg(feature = "macros")]
{
    // Use select! macro
    select! {
        result1 = async_operation_1() => {
            println!("Operation 1 completed: {:?}", result1);
        }
        result2 = async_operation_2() => {
            println!("Operation 2 completed: {:?}", result2);
        }
    }

    // Use join! macro
    let (result1, result2) = join!(
        async_operation_1(),
        async_operation_2()
    );

    // Use try_join! macro for Results
    let (result1, result2) = try_join!(
        fallible_async_operation_1(),
        fallible_async_operation_2()
    )?;
}

// Yield injection for simulation testing (requires macros feature)
#[cfg(feature = "macros")]
use switchy_async::{inject_yields, inject_yields_mod};

#[cfg(feature = "macros")]
#[inject_yields]
async fn my_async_function() {
    // Function body with automatic yield injection for deterministic testing
}

// Runtime entry-point macros
#[cfg(feature = "macros")]
#[switchy_async::main]
async fn main() {
    println!("Runs with the selected switchy_async backend");
}

#[cfg(feature = "macros")]
#[switchy_async::test]
async fn my_test() {
    assert_eq!(2 + 2, 4);
}
```

### Error Handling

```rust
use switchy_async::Error;

// Runtime errors
match runtime.wait() {
    Ok(()) => println!("Runtime completed successfully"),
    Err(Error::IO(io_err)) => println!("I/O error: {}", io_err),
    Err(Error::Join(join_err)) => println!("Join error: {}", join_err),
}

// Task join errors (when using task handles)
use switchy_async::task::JoinError;

let handle = runtime.spawn(async { /* ... */ });
match handle.await {
    Ok(result) => println!("Task completed: {:?}", result),
    Err(e) => println!("Task failed: {}", e),
}
```

## Feature Flags

### Backend Selection

- **`tokio`**: Enable Tokio async runtime
- **`simulator`**: Enable simulation runtime for testing

### Runtime Features

- **`rt-multi-thread`**: Multi-threaded runtime support
- **`fs`**: File system operations
- **`io`**: Async I/O operations
- **`net`**: Networking support
- **`process`**: Process management
- **`sync`**: Synchronization primitives (includes channels)
- **`time`**: Timing utilities
- **`util`**: Additional utilities
- **`macros`**: Async macros (select!, join!, try_join!, etc.)

### Macro Features

- **`macros`**: Enable async macros and yield injection utilities

## Runtime Comparison

### Tokio Runtime

- **Production**: Optimized for production use
- **Performance**: High-performance async execution
- **Ecosystem**: Full Tokio ecosystem support
- **Threading**: Multi-threaded execution

### Simulation Runtime

- **Testing**: Deterministic execution for tests
- **Reproducible**: Consistent behavior across runs
- **Debugging**: Easier debugging and tracing
- **Controlled**: Precise control over execution order

## Dependencies

Core dependencies:

- **thiserror**: Error handling
- **pin-project-lite**: Pin projection utilities
- **scoped-tls**: Scoped thread-local storage
- **log**: Logging facade

Feature-gated dependencies:

- **futures**: Core Future trait and utilities (enabled with backend features)
- **tokio**: Tokio async runtime (optional, enabled with `tokio` feature)
- **tokio-util**: Additional Tokio utilities (optional, enabled with `tokio` or `util` features)
- **flume**: MPSC/MPMC channel implementation (optional, enabled with `sync` feature)
- **switchy_async_macros**: Macro utilities (optional, enabled with `macros` feature)
- **switchy_random**: Random number generation for simulator (optional, enabled with `simulator` feature)
- **switchy_time**: Time utilities for simulator (optional, enabled with `simulator` feature)

## Integration

This package is designed for:

- **Application Runtime**: Main async runtime for applications
- **Testing**: Deterministic async testing with simulation
- **Library Development**: Runtime-agnostic async libraries
- **Performance**: High-performance async applications
- **Cross-Platform**: Consistent async behavior across platforms