1use core::fmt;
34use core::future::poll_fn;
35use core::task::{Context, Poll, ready};
36use std::io;
37use std::os::fd::AsFd;
38
39use super::caller::{self, Marks};
40use super::source::Kind;
41use super::{Handle, Interest, Ready};
42
43pub struct AsyncFd<T: AsFd> {
45 handle: Handle<T>,
46 interest: Interest,
47}
48
49pub struct AsyncFdReadyGuard<'a, T: AsFd> {
52 fd: &'a AsyncFd<T>,
53 marks: Marks,
54}
55
56pub struct AsyncFdReadyMutGuard<'a, T: AsFd> {
58 fd: &'a mut AsyncFd<T>,
59 marks: Marks,
60}
61
62#[derive(Debug)]
65pub struct TryIoError(());
66
67impl<T: AsFd> AsyncFd<T> {
68 pub fn new(inner: T) -> io::Result<Self> {
76 Self::with_interest(inner, Interest::READABLE | Interest::WRITABLE)
77 }
78
79 pub fn with_interest(inner: T, interest: Interest) -> io::Result<Self> {
85 Ok(Self {
86 handle: Handle::from_nonblocking(inner, Kind::Fd),
87 interest,
88 })
89 }
90
91 pub fn get_ref(&self) -> &T {
93 self.handle.get_ref()
94 }
95
96 pub fn get_mut(&mut self) -> &mut T {
98 self.handle.get_mut()
99 }
100
101 pub fn into_inner(self) -> T {
103 self.handle.into_inner()
104 }
105
106 pub fn poll_read_ready<'a>(
112 &'a self,
113 cx: &mut Context<'_>,
114 ) -> Poll<io::Result<AsyncFdReadyGuard<'a, T>>> {
115 let tick = ready!(self.handle.source().poll_fd_read_ready(cx))?;
116 Poll::Ready(Ok(AsyncFdReadyGuard {
117 fd: self,
118 marks: Marks {
119 ready: Ready::READABLE,
120 read: Some(tick),
121 write: None,
122 },
123 }))
124 }
125
126 pub fn poll_write_ready<'a>(
132 &'a self,
133 cx: &mut Context<'_>,
134 ) -> Poll<io::Result<AsyncFdReadyGuard<'a, T>>> {
135 let tick = ready!(self.handle.source().poll_fd_write_ready(cx))?;
136 Poll::Ready(Ok(AsyncFdReadyGuard {
137 fd: self,
138 marks: Marks {
139 ready: Ready::WRITABLE,
140 read: None,
141 write: Some(tick),
142 },
143 }))
144 }
145
146 fn sides(&self, interest: Interest) -> io::Result<(bool, bool)> {
149 let (read, write) = caller::sides(interest);
150 let (read, write) = (
151 read && self.interest.is_readable(),
152 write && self.interest.is_writable(),
153 );
154 if !read && !write {
155 return Err(io::Error::new(
156 io::ErrorKind::InvalidInput,
157 "the descriptor is not watched for that readiness",
158 ));
159 }
160 Ok((read, write))
161 }
162
163 fn poll_marks(&self, cx: &mut Context<'_>, interest: Interest) -> Poll<io::Result<Marks>> {
165 let (read, write) = self.sides(interest)?;
166 caller::poll_marks(self.handle.source(), cx, read, write)
167 }
168
169 pub async fn readable(&self) -> io::Result<AsyncFdReadyGuard<'_, T>> {
175 self.ready(Interest::READABLE).await
176 }
177
178 pub async fn writable(&self) -> io::Result<AsyncFdReadyGuard<'_, T>> {
184 self.ready(Interest::WRITABLE).await
185 }
186
187 pub async fn ready(&self, interest: Interest) -> io::Result<AsyncFdReadyGuard<'_, T>> {
194 let marks = poll_fn(|cx| self.poll_marks(cx, interest)).await?;
195 Ok(AsyncFdReadyGuard { fd: self, marks })
196 }
197
198 pub async fn readable_mut(&mut self) -> io::Result<AsyncFdReadyMutGuard<'_, T>> {
205 self.ready_mut(Interest::READABLE).await
206 }
207
208 pub async fn writable_mut(&mut self) -> io::Result<AsyncFdReadyMutGuard<'_, T>> {
215 self.ready_mut(Interest::WRITABLE).await
216 }
217
218 pub async fn ready_mut(
224 &mut self,
225 interest: Interest,
226 ) -> io::Result<AsyncFdReadyMutGuard<'_, T>> {
227 let marks = poll_fn(|cx| self.poll_marks(cx, interest)).await?;
228 Ok(AsyncFdReadyMutGuard { fd: self, marks })
229 }
230
231 pub async fn async_io<R>(
240 &self,
241 interest: Interest,
242 mut f: impl FnMut(&T) -> io::Result<R>,
243 ) -> io::Result<R> {
244 let sides = self.sides(interest)?;
245 caller::async_io(self.handle.source(), sides, || f(self.get_ref())).await
246 }
247
248 pub fn try_io<R>(
257 &self,
258 interest: Interest,
259 f: impl FnOnce(&T) -> io::Result<R>,
260 ) -> io::Result<R> {
261 caller::try_io(self.handle.source(), self.sides(interest)?, || {
262 f(self.get_ref())
263 })
264 }
265
266 fn clear(&self, marks: Marks) {
267 caller::clear(self.handle.source(), marks);
268 }
269}
270
271macro_rules! guard {
272 ($guard:ident) => {
273 impl<T: AsFd> $guard<'_, T> {
274 pub fn ready(&self) -> Ready {
276 self.marks.ready
277 }
278
279 pub fn clear_ready(&mut self) {
282 self.fd.clear(self.marks);
283 self.marks.ready = Ready::EMPTY;
284 }
285
286 pub fn clear_ready_matching(&mut self, ready: Ready) {
288 let mut marks = self.marks;
289 if !ready.is_readable() {
290 marks.read = None;
291 }
292 if !ready.is_writable() {
293 marks.write = None;
294 }
295 self.fd.clear(marks);
296 if ready.is_readable() {
297 self.marks.read = None;
298 }
299 if ready.is_writable() {
300 self.marks.write = None;
301 }
302 self.marks.ready = Ready::EMPTY;
303 if self.marks.read.is_some() {
304 self.marks.ready = self.marks.ready | Ready::READABLE;
305 }
306 if self.marks.write.is_some() {
307 self.marks.ready = self.marks.ready | Ready::WRITABLE;
308 }
309 }
310
311 pub fn retain_ready(&mut self) {}
313
314 pub fn get_inner(&self) -> &T {
316 self.fd.get_ref()
317 }
318 }
319
320 impl<T: AsFd> fmt::Debug for $guard<'_, T> {
321 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
322 f.debug_struct(stringify!($guard))
323 .field("ready", &self.marks.ready)
324 .finish_non_exhaustive()
325 }
326 }
327 };
328}
329
330guard!(AsyncFdReadyGuard);
331guard!(AsyncFdReadyMutGuard);
332
333impl<'a, T: AsFd> AsyncFdReadyGuard<'a, T> {
334 pub fn try_io<R>(
341 &mut self,
342 f: impl FnOnce(&'a AsyncFd<T>) -> io::Result<R>,
343 ) -> Result<io::Result<R>, TryIoError> {
344 match f(self.fd) {
345 Err(err) if err.kind() == io::ErrorKind::WouldBlock => {
346 self.clear_ready();
347 Err(TryIoError(()))
348 }
349 result => Ok(result),
350 }
351 }
352
353 pub fn get_ref(&self) -> &'a AsyncFd<T> {
355 self.fd
356 }
357}
358
359impl<T: AsFd> AsyncFdReadyMutGuard<'_, T> {
360 pub fn try_io<R>(
367 &mut self,
368 f: impl FnOnce(&mut AsyncFd<T>) -> io::Result<R>,
369 ) -> Result<io::Result<R>, TryIoError> {
370 match f(self.fd) {
371 Err(err) if err.kind() == io::ErrorKind::WouldBlock => {
372 self.clear_ready();
373 Err(TryIoError(()))
374 }
375 result => Ok(result),
376 }
377 }
378
379 pub fn get_ref(&self) -> &AsyncFd<T> {
381 self.fd
382 }
383
384 pub fn get_mut(&mut self) -> &mut AsyncFd<T> {
386 self.fd
387 }
388
389 pub fn get_inner_mut(&mut self) -> &mut T {
391 self.fd.get_mut()
392 }
393}
394
395impl<T: AsFd + fmt::Debug> fmt::Debug for AsyncFd<T> {
396 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
397 f.debug_struct("AsyncFd")
398 .field("inner", self.get_ref())
399 .finish_non_exhaustive()
400 }
401}
402
403impl fmt::Display for TryIoError {
404 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
405 f.write_str("the call would block")
406 }
407}
408
409impl std::error::Error for TryIoError {}
410
411#[cfg(test)]
412mod tests {
413 use std::io::{Read, Write};
414 use std::os::unix::net::UnixStream;
415 use std::time::{Duration, Instant};
416
417 use super::*;
418
419 fn on_ring() -> bool {
422 crate::Proactor::backend() == crate::IoBackend::IoUring
423 }
424
425 #[test]
431 fn an_edge_after_the_call_survives_the_clear() {
432 crate::block_on(async {
433 let (a, mut b) = UnixStream::pair().unwrap();
434 a.set_nonblocking(true).unwrap();
435 let fd = AsyncFd::with_interest(a, Interest::READABLE).unwrap();
436 let mut buf = [0u8; 8];
437 let mut guard = fd.readable().await.unwrap();
439 assert!(guard.try_io(|fd| fd.get_ref().read(&mut buf)).is_err());
440 b.write_all(b"r").unwrap();
441 let read = fd.async_io(Interest::READABLE, |mut a| a.read(&mut buf));
442 assert_eq!(read.await.unwrap(), 1);
443 let mut first = fd.readable().await.unwrap();
444 let err = fd.get_ref().read(&mut buf).unwrap_err();
445 assert_eq!(err.kind(), io::ErrorKind::WouldBlock);
446 b.write_all(b"x").unwrap();
447 if on_ring() {
448 first.clear_ready();
449 let n = fd.async_io(Interest::READABLE, |mut a| a.read(&mut buf));
450 assert_eq!(n.await.unwrap(), 1);
451 return;
452 }
453 let deadline = Instant::now() + Duration::from_secs(10);
454 loop {
455 crate::task::yield_now().await;
456 let look = fd.readable().await.unwrap();
457 if look.marks.read != first.marks.read {
458 break;
459 }
460 assert!(Instant::now() < deadline, "the driver never saw the edge");
461 }
462 first.clear_ready();
463 let mut cx = Context::from_waker(std::task::Waker::noop());
464 assert!(
465 fd.poll_read_ready(&mut cx).is_ready(),
466 "the edge after the call was lost to the clear"
467 );
468 assert_eq!(fd.get_ref().read(&mut buf).unwrap(), 1);
469 });
470 }
471
472 fn fill(fd: &AsyncFd<UnixStream>) -> usize {
474 let chunk = [5u8; 4096];
475 let mut sent = 0;
476 loop {
477 match fd.get_ref().write(&chunk) {
478 Ok(n) => sent += n,
479 Err(err) if err.kind() == io::ErrorKind::WouldBlock => return sent,
480 Err(err) => panic!("{err}"),
481 }
482 }
483 }
484
485 #[test]
488 fn a_write_edge_after_the_call_survives_the_clear() {
489 crate::block_on(async {
490 let (a, mut b) = UnixStream::pair().unwrap();
491 a.set_nonblocking(true).unwrap();
492 let fd = AsyncFd::with_interest(a, Interest::WRITABLE).unwrap();
493 let mut sink = vec![0u8; 1 << 20];
494 let mut guard = fd.writable().await.unwrap();
496 let sent = fill(&fd);
497 guard.clear_ready();
498 b.read_exact(&mut sink[..sent]).unwrap();
499 fd.writable().await.unwrap();
500 let mut first = fd.writable().await.unwrap();
501 let sent = fill(&fd);
502 b.read_exact(&mut sink[..sent]).unwrap();
503 if on_ring() {
504 first.clear_ready();
505 let n = fd.async_io(Interest::WRITABLE, |mut a| a.write(b"w"));
506 assert_eq!(n.await.unwrap(), 1);
507 return;
508 }
509 let deadline = Instant::now() + Duration::from_secs(10);
510 loop {
511 crate::task::yield_now().await;
512 let look = fd.writable().await.unwrap();
513 if look.marks.write != first.marks.write {
514 break;
515 }
516 assert!(Instant::now() < deadline, "the driver never saw the edge");
517 }
518 first.clear_ready();
519 let mut cx = Context::from_waker(std::task::Waker::noop());
520 assert!(
521 fd.poll_write_ready(&mut cx).is_ready(),
522 "the edge after the call was lost to the clear"
523 );
524 });
525 }
526}