use std::io;
use compio::{
BufResult,
io::{AsyncRead, AsyncWriteExt},
net::{UnixListener, UnixStream},
runtime::Runtime,
};
use compio_pool::{LocalPool, ManageConnection, Pool, cpu};
struct Buffers;
impl ManageConnection for Buffers {
type Connection = Vec<u8>;
type Error = io::Error;
async fn connect(&self) -> io::Result<Vec<u8>> {
Ok(Vec::with_capacity(16 * 1024))
}
async fn is_valid(&self, _buf: &mut Vec<u8>) -> io::Result<()> {
Ok(())
}
fn has_broken(&self, _buf: &mut Vec<u8>) -> bool {
false
}
}
fn main() -> io::Result<()> {
let path = std::env::args()
.nth(1)
.unwrap_or_else(|| "/tmp/compio-pool-echo.sock".into());
let capacity: u32 = std::env::args()
.nth(2)
.and_then(|s| s.parse().ok())
.unwrap_or(1024);
let _ = std::fs::remove_file(&path);
let pool = Pool::builder().max_size(capacity).build(Buffers);
if let Some(core) = cpu::cores().into_iter().next() {
cpu::pin_current(core);
}
println!("unix_echo on {path}: 1 worker, capacity {capacity}");
let runtime = Runtime::builder().build().expect("build compio runtime");
runtime.block_on(async move {
let local = pool.local();
let listener = UnixListener::bind(&path).await?;
loop {
let Ok((stream, _peer)) = listener.accept().await else {
continue;
};
compio::runtime::spawn(serve(local.clone(), stream)).detach();
}
})
}
async fn serve(local: LocalPool<Buffers>, mut stream: UnixStream) {
let mut lease = match local.get().await {
Ok(lease) => lease,
Err(_) => return,
};
loop {
let mut buf = std::mem::take(&mut *lease);
buf.clear();
let BufResult(read, buf) = stream.read(buf).await;
match read {
Ok(0) | Err(_) => {
*lease = buf;
return;
}
Ok(_) => {}
}
let BufResult(written, buf) = stream.write_all(buf).await;
*lease = buf;
if written.is_err() {
return;
}
}
}