Compio

MIT licensed crates.io docs.rs Azure DevOps builds

A thread-per-core Rust runtime with IOCP/io_uring/mio. The name comes from "completion-based IO". This crate is inspired by monoio.

Why not Tokio?

Tokio is a great generic-propose async runtime. However, it is poll-based, and even uses undocumented APIs on Windows. We would like some new high-level APIs to perform IOCP/io_uring.

Unlike tokio-uring, this runtime isn't Tokio-based. This is mainly because that no public APIs to control IOCP in mio, and tokio won't public APIs to control mio before mio reaches 1.0.

Why not monoio/tokio-uring?

They don't support Windows.

Quick start

With runtime feature enabled, we can use the high level APIs to perform fs & net IO.

```rust,norun use compio::{fs::File, task::blockon};

let buffer = blockon(async { let file = File::open("Cargo.toml").unwrap(); let (read, buffer) = file.readat(Vec::withcapacity(1024), 0).await; let read = read.unwrap(); asserteq!(read, buffer.len()); String::from_utf8(buffer).unwrap() }); println!("{}", buffer); ```

While you can also control the low-level driver manually:

```rust,no_run use arrayvec::ArrayVec; use compio::{ buf::IntoInner, driver::{AsRawFd, Driver, Entry, Poller}, fs::File, op::ReadAt, };

let mut driver = Driver::new().unwrap(); let file = File::open("Cargo.toml").unwrap(); // Attach the RawFd to driver first. driver.attach(file.asrawfd()).unwrap();

// Create operation and push it to the driver. let mut op = ReadAt::new(file.asrawfd(), 0, Vec::with_capacity(4096)); let ops = [(&mut op, 0).into()];

// Poll the driver and wait for IO completed. let mut entries = ArrayVec::::new(); unsafe { driver .poll(None, &mut ops.intoiter(), &mut entries) .unwrap(); } let entry = entries.drain(..).next().unwrap(); asserteq!(entry.user_data(), 0);

// Resize the buffer by return value. let n = entry.intoresult().unwrap(); let mut buffer = op.intoinner().intoinner(); unsafe { buffer.setlen(n); }

println!("{}", String::from_utf8(buffer).unwrap()); ```