Function nix::sys::aio::lio_listio

source ·
pub fn lio_listio(
    mode: LioMode,
    list: &mut [Pin<&mut dyn AsMut<aiocb>>],
    sigev_notify: SigevNotify
) -> Result<()>
👎Deprecated since 0.27.0: https://github.com/nix-rust/nix/issues/2017
Available on crate feature aio only.
Expand description

Submits multiple asynchronous I/O requests with a single system call.

They are not guaranteed to complete atomically, and the order in which the requests are carried out is not specified. Reads, and writes may be freely mixed.

§Examples

Use lio_listio to submit an aio operation and wait for its completion. In this case, there is no need to use aio_suspend to wait or error to poll. This mode is useful for otherwise-synchronous programs that want to execute a handful of I/O operations in parallel.

const WBUF: &[u8] = b"abcdef123456";
let mut f = tempfile().unwrap();
let mut aiow = Box::pin(AioWrite::new(
    f.as_fd(),
    2,      // offset
    WBUF,
    0,      // priority
    SigevNotify::SigevNone
));
lio_listio(LioMode::LIO_WAIT, &mut[aiow.as_mut()], SigevNotify::SigevNone)
    .unwrap();
// At this point, we are guaranteed that aiow is complete.
assert_eq!(aiow.as_mut().aio_return().unwrap(), WBUF.len());

Use lio_listio to submit multiple asynchronous operations with a single syscall, but receive notification individually. This is an efficient technique for reducing overall context-switch overhead, especially when combined with kqueue.

const WBUF: &[u8] = b"abcdef123456";
let mut f = tempfile().unwrap();
let mut aiow = Box::pin(AioWrite::new(
    f.as_fd(),
    2,      // offset
    WBUF,
    0,      // priority
    SigevNotify::SigevNone
));
lio_listio(LioMode::LIO_NOWAIT, &mut[aiow.as_mut()], SigevNotify::SigevNone)
    .unwrap();
// We must wait for the completion of each individual operation
while (aiow.as_mut().error() == Err(Errno::EINPROGRESS)) {
    thread::sleep(time::Duration::from_millis(10));
}
assert_eq!(aiow.as_mut().aio_return().unwrap(), WBUF.len());

Use lio_listio to submit multiple operations, and receive notification only when all of them are complete. This can be useful when there is some logical relationship between the operations. But beware! Errors or system resource limitations may cause lio_listio to return EIO, EAGAIN, or EINTR, in which case some but not all operations may have been submitted. In that case, you must check the status of each individual operation, and possibly resubmit some.

pub static SIGNALED: AtomicBool = AtomicBool::new(false);

extern fn sigfunc(_: c_int) {
    SIGNALED.store(true, Ordering::Relaxed);
}
let sa = SigAction::new(SigHandler::Handler(sigfunc),
                        SaFlags::SA_RESETHAND,
                        SigSet::empty());
SIGNALED.store(false, Ordering::Relaxed);
unsafe { sigaction(Signal::SIGUSR2, &sa) }.unwrap();

const WBUF: &[u8] = b"abcdef123456";
let mut f = tempfile().unwrap();
let mut aiow = Box::pin(AioWrite::new(
    f.as_fd(),
    2,      // offset
    WBUF,
    0,      // priority
    SigevNotify::SigevNone
));
let sev = SigevNotify::SigevSignal { signal: Signal::SIGUSR2, si_value: 0 };
lio_listio(LioMode::LIO_NOWAIT, &mut[aiow.as_mut()], sev).unwrap();
while !SIGNALED.load(Ordering::Relaxed) {
    thread::sleep(time::Duration::from_millis(10));
}
// At this point, since `lio_listio` returned success and delivered its
// notification, we know that all operations are complete.
assert_eq!(aiow.as_mut().aio_return().unwrap(), WBUF.len());