Crate compio

source ·
Expand description

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.

use compio::{fs::File, task::block_on};

let buffer = block_on(async {
    let file = File::open("Cargo.toml").unwrap();
    let (read, buffer) = file.read_at(Vec::with_capacity(1024), 0).await;
    let read = read.unwrap();
    assert_eq!(read, buffer.len());
    String::from_utf8(buffer).unwrap()
});
println!("{}", buffer);

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

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.as_raw_fd()).unwrap();

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

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

// Resize the buffer by return value.
let n = entry.into_result().unwrap();
let mut buffer = op.into_inner().into_inner();
unsafe {
    buffer.set_len(n);
}

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

Modules

  • Utilities for working with buffers.
  • The platform-specified driver. Some types differ by compilation target.
  • Asynchronous events.
  • Filesystem manipulation operations.
  • Network related.
  • The async operations. Types in this mod represents the low-level operations passed to kernel. The operation itself doesn’t perform anything. You need to pass them to crate::driver::Driver, and poll the driver.
  • Asynchronous signal handling.
  • The runtime of compio. We don’t expose the runtime struct because there could be only one runtime in each thread.
  • Utilities for tracking time.

Type Aliases

  • A specialized Result type for operations with buffers.