A10
The A10 io_uring library.
This library is meant as a low-level library safely exposing the io_uring API.
For simplicity this only has two main types and a number of helper types:
Ring
is a wrapper around io_uring used to poll for completion events.
AsyncFd
is a wrapper around a file descriptor that provides a safe API to
schedule operations.
Linux Required
Currently this requires a fairly new Linux kernel version, everything should
work on Linux v6.1 and up.
Examples
A10 is expected to be integrated into a Future
runtime, but it can work as a
stand-alone library.
use std::path::PathBuf;
use std::future::Future;
use std::io;
use a10::{Extract, Ring, SubmissionQueue};
fn main() -> io::Result<()> {
let mut ring = Ring::new(8)?;
let sq = ring.submission_queue().clone();
let future = cat(sq, "./src/lib.rs");
block_on(&mut ring, future)
}
async fn cat(sq: SubmissionQueue, filename: &str) -> io::Result<()> {
let filename = PathBuf::from(filename);
let file = a10::fs::OpenOptions::new().open(sq.clone(), filename).await?;
let buf = file.read(Vec::with_capacity(32 * 1024)).await?;
let stdout = a10::io::stdout(sq);
let (buf, n) = stdout.write(buf).extract().await?;
Ok(())
}
fn block_on<Fut, T>(ring: &mut Ring, future: Fut) -> Fut::Output
where
Fut: Future<Output = io::Result<T>>
{
use std::task::{self, RawWaker, RawWakerVTable, Poll};
use std::ptr;
let mut future = std::pin::pin!(future);
let waker = unsafe { task::Waker::from_raw(RawWaker::new(ptr::null(), &WAKER_VTABLE)) };
let mut ctx = task::Context::from_waker(&waker);
loop {
match future.as_mut().poll(&mut ctx) {
Poll::Ready(result) => return result,
Poll::Pending => {
ring.poll(None)?;
}
}
}
static WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new(
|_| RawWaker::new(ptr::null(), &WAKER_VTABLE),
|_| {},
|_| {},
|_| {},
);
}
For more examples see the examples directory.