Unit tests pass

Fixed a nasty deadlock in reqnot
This commit is contained in:
2026-01-19 00:56:03 +01:00
parent 6a3c1d5917
commit 48942b3b2c
15 changed files with 223 additions and 85 deletions

View File

@@ -27,7 +27,6 @@ pub fn pipe(size: usize) -> (Writer, Reader) {
size,
mut read_waker,
mut write_waker,
mut flush_waker,
reader_dropped,
writer_dropped,
// irrelevant if correctly dropped
@@ -42,7 +41,6 @@ pub fn pipe(size: usize) -> (Writer, Reader) {
}
read_waker.drop();
write_waker.drop();
flush_waker.drop();
unsafe { dealloc(start, pipe_layout(size)) }
}
let state = Box::into_raw(Box::new(AsyncRingbuffer {
@@ -53,7 +51,6 @@ pub fn pipe(size: usize) -> (Writer, Reader) {
write_idx: 0,
read_waker: Trigger::empty(),
write_waker: Trigger::empty(),
flush_waker: Trigger::empty(),
reader_dropped: false,
writer_dropped: false,
drop,
@@ -110,21 +107,22 @@ struct AsyncRingbuffer {
write_idx: usize,
read_waker: Trigger,
write_waker: Trigger,
flush_waker: Trigger,
reader_dropped: bool,
writer_dropped: bool,
drop: extern "C" fn(*const ()),
}
impl AsyncRingbuffer {
fn wake_reader(&mut self) { self.read_waker.invoke() }
fn wake_writer(&mut self) { self.write_waker.invoke() }
fn drop_writer(&mut self) {
self.read_waker.invoke();
self.wake_reader();
self.writer_dropped = true;
if self.reader_dropped {
(self.drop)(self.state)
}
}
fn drop_reader(&mut self) {
self.write_waker.invoke();
self.wake_writer();
self.reader_dropped = true;
if self.writer_dropped {
(self.drop)(self.state)
@@ -134,25 +132,14 @@ impl AsyncRingbuffer {
if self.reader_dropped {
return Poll::Ready(Err(broken_pipe_error()));
}
self.read_waker.invoke();
self.write_waker.drop();
self.write_waker = Trigger::new(waker.clone());
Poll::Pending
}
fn flush_wait<T>(&mut self, waker: &Waker) -> Poll<io::Result<T>> {
if self.reader_dropped {
return Poll::Ready(Err(broken_pipe_error()));
}
self.read_waker.invoke();
self.flush_waker.drop();
self.flush_waker = Trigger::new(waker.clone());
Poll::Pending
}
fn reader_wait(&mut self, waker: &Waker) -> Poll<io::Result<usize>> {
if self.writer_dropped {
return Poll::Ready(Err(broken_pipe_error()));
}
self.write_waker.invoke();
self.read_waker.drop();
self.read_waker = Trigger::new(waker.clone());
Poll::Pending
@@ -234,7 +221,7 @@ impl Writer {
return Err(SyncWriteError::BufferFull);
}
state.wrapping_write_unchecked(data);
state.write_waker.invoke();
state.wake_reader();
Ok(())
}
}
@@ -255,7 +242,7 @@ impl AsyncWrite for Writer {
fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
unsafe {
let data = self.as_mut().get_state()?;
if data.is_empty() { Poll::Ready(Ok(())) } else { data.flush_wait(cx.waker()) }
if data.is_empty() { Poll::Ready(Ok(())) } else { data.writer_wait(cx.waker()) }
}
}
fn poll_write(
@@ -263,12 +250,15 @@ impl AsyncWrite for Writer {
cx: &mut Context<'_>,
buf: &[u8],
) -> Poll<io::Result<usize>> {
if buf.is_empty() {
return Poll::Ready(Ok(0));
}
unsafe {
let data = self.as_mut().get_state()?;
if !buf.is_empty() && data.is_empty() {
data.read_waker.invoke();
if data.is_empty() {
data.wake_reader();
}
if !buf.is_empty() && data.is_full() {
if data.is_full() {
data.writer_wait(cx.waker())
} else {
Poll::Ready(Ok(data.wrapping_write_unchecked(buf)))
@@ -300,7 +290,7 @@ impl AsyncRead for Reader {
let data = self.0.as_mut().expect("Cannot be null");
let AsyncRingbuffer { read_idx, write_idx, size, .. } = *data;
if !buf.is_empty() && data.is_full() {
data.write_waker.invoke();
data.wake_writer();
}
let poll = if !buf.is_empty() && data.is_empty() {
// Nothing to read, waiting...
@@ -322,8 +312,8 @@ impl AsyncRead for Reader {
data.non_wrapping_read_unchecked(&mut start[0..start_count]);
Poll::Ready(Ok(end.len() + start_count))
};
if !buf.is_empty() && data.is_empty() {
data.flush_waker.invoke();
if data.is_empty() {
data.wake_writer();
}
poll
}