lio 0.4.1

A platform-independent async I/O library with native support for io_uring (Linux), IOCP (Windows), and kqueue (macOS)
Documentation
#![cfg(linux)]

use lio::{Lio, api, api::resource::Resource};
use std::os::fd::FromRawFd;
use std::time::Instant;

#[test]
#[ignore]
fn test_close_timing() {
  let mut lio = Lio::new(64).unwrap();

  let start = Instant::now();
  let mut pipe1_fds = [0i32; 2];
  let mut pipe2_fds = [0i32; 2];
  unsafe {
    assert_eq!(libc::pipe(pipe1_fds.as_mut_ptr()), 0);
    assert_eq!(libc::pipe(pipe2_fds.as_mut_ptr()), 0);
  }

  // Wrap raw fds in Resource for tee (which requires AsResource)
  let pipe1_read = unsafe { Resource::from_raw_fd(pipe1_fds[0]) };
  let pipe2_write = unsafe { Resource::from_raw_fd(pipe2_fds[1]) };

  // Write some data
  let test_data = b"Hello!";
  unsafe {
    libc::write(
      pipe1_fds[1],
      test_data.as_ptr() as *const libc::c_void,
      test_data.len(),
    );
  }

  // Do a tee operation
  let tee_start = Instant::now();
  let mut tee_recv =
    api::tee(&pipe1_read, &pipe2_write, test_data.len() as u32)
      .with_lio(&mut lio)
      .send();

  // Forget the Resources so they don't close fds on drop (we close them manually below)
  std::mem::forget(pipe1_read);
  std::mem::forget(pipe2_write);

  // Try multiple ticks - some operations need more than one
  for i in 0..10 {
    lio.try_run().unwrap();
    if let Some(result) = tee_recv.try_recv() {
      result.expect("test_close_timing: tee operation failed");
      break;
    }
    if i == 9 {
      panic!(
        "test_close_timing: tee operation did not complete after 10 ticks"
      );
    }
  }
  println!("Tee took: {:?}", tee_start.elapsed());

  // Close all file descriptors (close takes RawFd)
  let mut close1_recv = api::close(pipe1_fds[0]).with_lio(&mut lio).send();
  let mut close2_recv = api::close(pipe1_fds[1]).with_lio(&mut lio).send();
  let mut close3_recv = api::close(pipe2_fds[0]).with_lio(&mut lio).send();
  let mut close4_recv = api::close(pipe2_fds[1]).with_lio(&mut lio).send();

  // Try multiple ticks for close operations too
  for i in 0..10 {
    lio.try_run().unwrap();

    let close1_done = close1_recv.try_recv().is_some();
    let close2_done = close2_recv.try_recv().is_some();
    let close3_done = close3_recv.try_recv().is_some();
    let close4_done = close4_recv.try_recv().is_some();

    if close1_done && close2_done && close3_done && close4_done {
      break;
    }

    if i == 9 {
      panic!(
        "test_close_timing: not all close operations completed after 10 ticks"
      );
    }
  }

  println!("Total execution took: {:?}", start.elapsed());
}