use std::cmp; use std::future::Future; use std::io; use std::io::prelude::*; use std::mem::MaybeUninit; use std::pin::Pin; use std::task::{ready, Context, Poll};
/// `T` should not implement _both_ Read and Write. #[derive(Debug)] pub(crate) struct Blocking<T> {
inner: Option<T>,
state: State<T>, /// `true` if the lower IO layer needs flushing.
need_flush: bool,
}
cfg_io_blocking! { impl<T> Blocking<T> { /// # Safety /// /// The `Read` implementation of `inner` must never read from the buffer /// it is borrowing and must correctly report the length of the data /// written into the buffer. #[cfg_attr(feature = "fs", allow(dead_code))] pub(crate) unsafefn new(inner: T) -> Blocking<T> {
Blocking {
inner: Some(inner),
state: State::Idle(Some(Buf::with_capacity(0))),
need_flush: false,
}
}
}
}
fn poll_flush(mutself: Pin<&mutSelf>, cx: &>mut Context<'_>) -> Poll<Result<(), io::Error>> { loop { let need_flush = self.need_flush; matchself.state { // The buffer is not used here
State::Idle(refmut buf_cell) => { if need_flush { let buf = buf_cell.take().unwrap(); letmut inner = self.inner.take().unwrap();
self.state = State::Busy(sys::run(move || { let res = inner.flush().map(|()| 0);
(res, buf, inner)
}));
/// # Safety /// /// `rd` must not read from the buffer `read` is borrowing and must correctly /// report the length of the data written into the buffer. pub(crate) unsafefn read_from<T: Read>(
&mutself,
rd: &mut T,
max_buf_size: usize,
) -> io::Result<usize> {
assert!(self.is_empty()); self.buf.reserve(max_buf_size);
let buf = &mutself.buf.spare_capacity_mut()[..max_buf_size]; // SAFETY: The memory may be uninitialized, but `rd.read` will only write to the buffer. let buf = unsafe { &mut *(buf as *mut [MaybeUninit<u8>] as *mut [u8]) }; let res = uninterruptibly!(rd.read(buf));
iflet Ok(n) = res { // SAFETY: the caller promises that `rd.read` initializes // a section of `buf` and correctly reports that length. // The `self.is_empty()` assertion verifies that `n` // equals the length of the `buf` capacity that was written // to (and that `buf` isn't being shrunk). unsafe { self.buf.set_len(n) }
} else { self.buf.clear();
}
// `write_all` already ignores interrupts let res = wr.write_all(&self.buf); self.buf.clear();
res
}
}
cfg_io_uring! { impl Buf { /// Prepare the internal buffer for an io-uring read operation. /// /// Returns a pointer to the spare capacity and the length available /// for the kernel to write into. pub(crate) fn prepare_uring_read(&mutself, max_buf_size: usize) -> (*mut u8, u32) {
assert!(self.is_empty()); self.buf.reserve(max_buf_size); let spare = self.buf.spare_capacity_mut(); let len = std::cmp::min(spare.len(), max_buf_size); let ptr = spare.as_mut_ptr().cast::<u8>();
(ptr, len as u32)
}
/// Complete an io-uring read operation. /// /// # Safety /// /// The caller must ensure that the kernel wrote exactly `n` bytes /// into the buffer that was returned by `prepare_uring_read`. pub(crate) unsafefn complete_uring_read(&mutself, n: usize) {
assert_eq!(self.pos, 0); // SAFETY: `prepare_uring_read` handed out a pointer to // `self.buf.spare_capacity_mut()` after asserting it's empty. // The caller guarantees the kernel initialised exactly `n` bytes // starting at that pointer, so bytes `0..n` are now initialised and // it is sound to set the Vec length to `n`. unsafe { self.buf.set_len(n) };
}
}
}
cfg_fs! { impl Buf { pub(crate) fn discard_read(&mutself) -> i64 { let ret = -(self.bytes().len() as i64); self.pos = 0; self.buf.truncate(0);
ret
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.