Function nix::sys::aio::lio_listio
source · pub fn lio_listio(
mode: LioMode,
list: &mut [Pin<&mut dyn AsMut<aiocb>>],
sigev_notify: SigevNotify<'_>,
) -> Result<()>
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());