1use crate::io::{Interest, Ready};
2use crate::runtime::io::{ReadyEvent, Registration};
3use crate::runtime::scheduler;
4
5use mio::unix::SourceFd;
6use std::io;
7use std::os::unix::io::{AsRawFd, RawFd};
8use std::{task::Context, task::Poll};
9
10/// Associates an IO object backed by a Unix file descriptor with the tokio
11/// reactor, allowing for readiness to be polled. The file descriptor must be of
12/// a type that can be used with the OS polling facilities (ie, `poll`, `epoll`,
13/// `kqueue`, etc), such as a network socket or pipe, and the file descriptor
14/// must have the nonblocking mode set to true.
15///
16/// Creating an [`AsyncFd`] registers the file descriptor with the current tokio
17/// Reactor, allowing you to directly await the file descriptor being readable
18/// or writable. Once registered, the file descriptor remains registered until
19/// the [`AsyncFd`] is dropped.
20///
21/// The [`AsyncFd`] takes ownership of an arbitrary object to represent the IO
22/// object. It is intended that this object will handle closing the file
23/// descriptor when it is dropped, avoiding resource leaks and ensuring that the
24/// [`AsyncFd`] can clean up the registration before closing the file descriptor.
25/// The [`AsyncFd::into_inner`] function can be used to extract the inner object
26/// to retake control from the tokio IO reactor.
27///
28/// The inner object is required to implement [`AsRawFd`]. This file descriptor
29/// must not change while [`AsyncFd`] owns the inner object, i.e. the
30/// [`AsRawFd::as_raw_fd`] method on the inner type must always return the same
31/// file descriptor when called multiple times. Failure to uphold this results
32/// in unspecified behavior in the IO driver, which may include breaking
33/// notifications for other sockets/etc.
34///
35/// Polling for readiness is done by calling the async functions [`readable`]
36/// and [`writable`]. These functions complete when the associated readiness
37/// condition is observed. Any number of tasks can query the same `AsyncFd` in
38/// parallel, on the same or different conditions.
39///
40/// On some platforms, the readiness detecting mechanism relies on
41/// edge-triggered notifications. This means that the OS will only notify Tokio
42/// when the file descriptor transitions from not-ready to ready. For this to
43/// work you should first try to read or write and only poll for readiness
44/// if that fails with an error of [`std::io::ErrorKind::WouldBlock`].
45///
46/// Tokio internally tracks when it has received a ready notification, and when
47/// readiness checking functions like [`readable`] and [`writable`] are called,
48/// if the readiness flag is set, these async functions will complete
49/// immediately. This however does mean that it is critical to ensure that this
50/// ready flag is cleared when (and only when) the file descriptor ceases to be
51/// ready. The [`AsyncFdReadyGuard`] returned from readiness checking functions
52/// serves this function; after calling a readiness-checking async function,
53/// you must use this [`AsyncFdReadyGuard`] to signal to tokio whether the file
54/// descriptor is no longer in a ready state.
55///
56/// ## Use with to a poll-based API
57///
58/// In some cases it may be desirable to use `AsyncFd` from APIs similar to
59/// [`TcpStream::poll_read_ready`]. The [`AsyncFd::poll_read_ready`] and
60/// [`AsyncFd::poll_write_ready`] functions are provided for this purpose.
61/// Because these functions don't create a future to hold their state, they have
62/// the limitation that only one task can wait on each direction (read or write)
63/// at a time.
64///
65/// # Examples
66///
67/// This example shows how to turn [`std::net::TcpStream`] asynchronous using
68/// `AsyncFd`. It implements the read/write operations both as an `async fn`
69/// and using the IO traits [`AsyncRead`] and [`AsyncWrite`].
70///
71/// ```no_run
72/// use futures::ready;
73/// use std::io::{self, Read, Write};
74/// use std::net::TcpStream;
75/// use std::pin::Pin;
76/// use std::task::{Context, Poll};
77/// use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
78/// use tokio::io::unix::AsyncFd;
79///
80/// pub struct AsyncTcpStream {
81/// inner: AsyncFd<TcpStream>,
82/// }
83///
84/// impl AsyncTcpStream {
85/// pub fn new(tcp: TcpStream) -> io::Result<Self> {
86/// tcp.set_nonblocking(true)?;
87/// Ok(Self {
88/// inner: AsyncFd::new(tcp)?,
89/// })
90/// }
91///
92/// pub async fn read(&self, out: &mut [u8]) -> io::Result<usize> {
93/// loop {
94/// let mut guard = self.inner.readable().await?;
95///
96/// match guard.try_io(|inner| inner.get_ref().read(out)) {
97/// Ok(result) => return result,
98/// Err(_would_block) => continue,
99/// }
100/// }
101/// }
102///
103/// pub async fn write(&self, buf: &[u8]) -> io::Result<usize> {
104/// loop {
105/// let mut guard = self.inner.writable().await?;
106///
107/// match guard.try_io(|inner| inner.get_ref().write(buf)) {
108/// Ok(result) => return result,
109/// Err(_would_block) => continue,
110/// }
111/// }
112/// }
113/// }
114///
115/// impl AsyncRead for AsyncTcpStream {
116/// fn poll_read(
117/// self: Pin<&mut Self>,
118/// cx: &mut Context<'_>,
119/// buf: &mut ReadBuf<'_>
120/// ) -> Poll<io::Result<()>> {
121/// loop {
122/// let mut guard = ready!(self.inner.poll_read_ready(cx))?;
123///
124/// let unfilled = buf.initialize_unfilled();
125/// match guard.try_io(|inner| inner.get_ref().read(unfilled)) {
126/// Ok(Ok(len)) => {
127/// buf.advance(len);
128/// return Poll::Ready(Ok(()));
129/// },
130/// Ok(Err(err)) => return Poll::Ready(Err(err)),
131/// Err(_would_block) => continue,
132/// }
133/// }
134/// }
135/// }
136///
137/// impl AsyncWrite for AsyncTcpStream {
138/// fn poll_write(
139/// self: Pin<&mut Self>,
140/// cx: &mut Context<'_>,
141/// buf: &[u8]
142/// ) -> Poll<io::Result<usize>> {
143/// loop {
144/// let mut guard = ready!(self.inner.poll_write_ready(cx))?;
145///
146/// match guard.try_io(|inner| inner.get_ref().write(buf)) {
147/// Ok(result) => return Poll::Ready(result),
148/// Err(_would_block) => continue,
149/// }
150/// }
151/// }
152///
153/// fn poll_flush(
154/// self: Pin<&mut Self>,
155/// cx: &mut Context<'_>,
156/// ) -> Poll<io::Result<()>> {
157/// // tcp flush is a no-op
158/// Poll::Ready(Ok(()))
159/// }
160///
161/// fn poll_shutdown(
162/// self: Pin<&mut Self>,
163/// cx: &mut Context<'_>,
164/// ) -> Poll<io::Result<()>> {
165/// self.inner.get_ref().shutdown(std::net::Shutdown::Write)?;
166/// Poll::Ready(Ok(()))
167/// }
168/// }
169/// ```
170///
171/// [`readable`]: method@Self::readable
172/// [`writable`]: method@Self::writable
173/// [`AsyncFdReadyGuard`]: struct@self::AsyncFdReadyGuard
174/// [`TcpStream::poll_read_ready`]: struct@crate::net::TcpStream
175/// [`AsyncRead`]: trait@crate::io::AsyncRead
176/// [`AsyncWrite`]: trait@crate::io::AsyncWrite
177pub struct AsyncFd<T: AsRawFd> {
178 registration: Registration,
179 // The inner value is always present. the Option is required for `drop` and `into_inner`.
180 // In all other methods `unwrap` is valid, and will never panic.
181 inner: Option<T>,
182}
183
184/// Represents an IO-ready event detected on a particular file descriptor that
185/// has not yet been acknowledged. This is a `must_use` structure to help ensure
186/// that you do not forget to explicitly clear (or not clear) the event.
187///
188/// This type exposes an immutable reference to the underlying IO object.
189#[must_use = "You must explicitly choose whether to clear the readiness state by calling a method on ReadyGuard"]
190pub struct AsyncFdReadyGuard<'a, T: AsRawFd> {
191 async_fd: &'a AsyncFd<T>,
192 event: Option<ReadyEvent>,
193}
194
195/// Represents an IO-ready event detected on a particular file descriptor that
196/// has not yet been acknowledged. This is a `must_use` structure to help ensure
197/// that you do not forget to explicitly clear (or not clear) the event.
198///
199/// This type exposes a mutable reference to the underlying IO object.
200#[must_use = "You must explicitly choose whether to clear the readiness state by calling a method on ReadyGuard"]
201pub struct AsyncFdReadyMutGuard<'a, T: AsRawFd> {
202 async_fd: &'a mut AsyncFd<T>,
203 event: Option<ReadyEvent>,
204}
205
206impl<T: AsRawFd> AsyncFd<T> {
207 /// Creates an [`AsyncFd`] backed by (and taking ownership of) an object
208 /// implementing [`AsRawFd`]. The backing file descriptor is cached at the
209 /// time of creation.
210 ///
211 /// Only configures the [`Interest::READABLE`] and [`Interest::WRITABLE`] interests. For more
212 /// control, use [`AsyncFd::with_interest`].
213 ///
214 /// This method must be called in the context of a tokio runtime.
215 ///
216 /// # Panics
217 ///
218 /// This function panics if there is no current reactor set, or if the `rt`
219 /// feature flag is not enabled.
220 #[inline]
221 #[track_caller]
222 pub fn new(inner: T) -> io::Result<Self>
223 where
224 T: AsRawFd,
225 {
226 Self::with_interest(inner, Interest::READABLE | Interest::WRITABLE)
227 }
228
229 /// Creates an [`AsyncFd`] backed by (and taking ownership of) an object
230 /// implementing [`AsRawFd`], with a specific [`Interest`]. The backing
231 /// file descriptor is cached at the time of creation.
232 ///
233 /// # Panics
234 ///
235 /// This function panics if there is no current reactor set, or if the `rt`
236 /// feature flag is not enabled.
237 #[inline]
238 #[track_caller]
239 pub fn with_interest(inner: T, interest: Interest) -> io::Result<Self>
240 where
241 T: AsRawFd,
242 {
243 Self::new_with_handle_and_interest(inner, scheduler::Handle::current(), interest)
244 }
245
246 #[track_caller]
247 pub(crate) fn new_with_handle_and_interest(
248 inner: T,
249 handle: scheduler::Handle,
250 interest: Interest,
251 ) -> io::Result<Self> {
252 let fd = inner.as_raw_fd();
253
254 let registration =
255 Registration::new_with_interest_and_handle(&mut SourceFd(&fd), interest, handle)?;
256
257 Ok(AsyncFd {
258 registration,
259 inner: Some(inner),
260 })
261 }
262
263 /// Returns a shared reference to the backing object of this [`AsyncFd`].
264 #[inline]
265 pub fn get_ref(&self) -> &T {
266 self.inner.as_ref().unwrap()
267 }
268
269 /// Returns a mutable reference to the backing object of this [`AsyncFd`].
270 #[inline]
271 pub fn get_mut(&mut self) -> &mut T {
272 self.inner.as_mut().unwrap()
273 }
274
275 fn take_inner(&mut self) -> Option<T> {
276 let inner = self.inner.take()?;
277 let fd = inner.as_raw_fd();
278
279 let _ = self.registration.deregister(&mut SourceFd(&fd));
280
281 Some(inner)
282 }
283
284 /// Deregisters this file descriptor and returns ownership of the backing
285 /// object.
286 pub fn into_inner(mut self) -> T {
287 self.take_inner().unwrap()
288 }
289
290 /// Polls for read readiness.
291 ///
292 /// If the file descriptor is not currently ready for reading, this method
293 /// will store a clone of the [`Waker`] from the provided [`Context`]. When the
294 /// file descriptor becomes ready for reading, [`Waker::wake`] will be called.
295 ///
296 /// Note that on multiple calls to [`poll_read_ready`] or
297 /// [`poll_read_ready_mut`], only the `Waker` from the `Context` passed to the
298 /// most recent call is scheduled to receive a wakeup. (However,
299 /// [`poll_write_ready`] retains a second, independent waker).
300 ///
301 /// This method is intended for cases where creating and pinning a future
302 /// via [`readable`] is not feasible. Where possible, using [`readable`] is
303 /// preferred, as this supports polling from multiple tasks at once.
304 ///
305 /// This method takes `&self`, so it is possible to call this method
306 /// concurrently with other methods on this struct. This method only
307 /// provides shared access to the inner IO resource when handling the
308 /// [`AsyncFdReadyGuard`].
309 ///
310 /// [`poll_read_ready`]: method@Self::poll_read_ready
311 /// [`poll_read_ready_mut`]: method@Self::poll_read_ready_mut
312 /// [`poll_write_ready`]: method@Self::poll_write_ready
313 /// [`readable`]: method@Self::readable
314 /// [`Context`]: struct@std::task::Context
315 /// [`Waker`]: struct@std::task::Waker
316 /// [`Waker::wake`]: method@std::task::Waker::wake
317 pub fn poll_read_ready<'a>(
318 &'a self,
319 cx: &mut Context<'_>,
320 ) -> Poll<io::Result<AsyncFdReadyGuard<'a, T>>> {
321 let event = ready!(self.registration.poll_read_ready(cx))?;
322
323 Poll::Ready(Ok(AsyncFdReadyGuard {
324 async_fd: self,
325 event: Some(event),
326 }))
327 }
328
329 /// Polls for read readiness.
330 ///
331 /// If the file descriptor is not currently ready for reading, this method
332 /// will store a clone of the [`Waker`] from the provided [`Context`]. When the
333 /// file descriptor becomes ready for reading, [`Waker::wake`] will be called.
334 ///
335 /// Note that on multiple calls to [`poll_read_ready`] or
336 /// [`poll_read_ready_mut`], only the `Waker` from the `Context` passed to the
337 /// most recent call is scheduled to receive a wakeup. (However,
338 /// [`poll_write_ready`] retains a second, independent waker).
339 ///
340 /// This method is intended for cases where creating and pinning a future
341 /// via [`readable`] is not feasible. Where possible, using [`readable`] is
342 /// preferred, as this supports polling from multiple tasks at once.
343 ///
344 /// This method takes `&mut self`, so it is possible to access the inner IO
345 /// resource mutably when handling the [`AsyncFdReadyMutGuard`].
346 ///
347 /// [`poll_read_ready`]: method@Self::poll_read_ready
348 /// [`poll_read_ready_mut`]: method@Self::poll_read_ready_mut
349 /// [`poll_write_ready`]: method@Self::poll_write_ready
350 /// [`readable`]: method@Self::readable
351 /// [`Context`]: struct@std::task::Context
352 /// [`Waker`]: struct@std::task::Waker
353 /// [`Waker::wake`]: method@std::task::Waker::wake
354 pub fn poll_read_ready_mut<'a>(
355 &'a mut self,
356 cx: &mut Context<'_>,
357 ) -> Poll<io::Result<AsyncFdReadyMutGuard<'a, T>>> {
358 let event = ready!(self.registration.poll_read_ready(cx))?;
359
360 Poll::Ready(Ok(AsyncFdReadyMutGuard {
361 async_fd: self,
362 event: Some(event),
363 }))
364 }
365
366 /// Polls for write readiness.
367 ///
368 /// If the file descriptor is not currently ready for writing, this method
369 /// will store a clone of the [`Waker`] from the provided [`Context`]. When the
370 /// file descriptor becomes ready for writing, [`Waker::wake`] will be called.
371 ///
372 /// Note that on multiple calls to [`poll_write_ready`] or
373 /// [`poll_write_ready_mut`], only the `Waker` from the `Context` passed to the
374 /// most recent call is scheduled to receive a wakeup. (However,
375 /// [`poll_read_ready`] retains a second, independent waker).
376 ///
377 /// This method is intended for cases where creating and pinning a future
378 /// via [`writable`] is not feasible. Where possible, using [`writable`] is
379 /// preferred, as this supports polling from multiple tasks at once.
380 ///
381 /// This method takes `&self`, so it is possible to call this method
382 /// concurrently with other methods on this struct. This method only
383 /// provides shared access to the inner IO resource when handling the
384 /// [`AsyncFdReadyGuard`].
385 ///
386 /// [`poll_read_ready`]: method@Self::poll_read_ready
387 /// [`poll_write_ready`]: method@Self::poll_write_ready
388 /// [`poll_write_ready_mut`]: method@Self::poll_write_ready_mut
389 /// [`writable`]: method@Self::readable
390 /// [`Context`]: struct@std::task::Context
391 /// [`Waker`]: struct@std::task::Waker
392 /// [`Waker::wake`]: method@std::task::Waker::wake
393 pub fn poll_write_ready<'a>(
394 &'a self,
395 cx: &mut Context<'_>,
396 ) -> Poll<io::Result<AsyncFdReadyGuard<'a, T>>> {
397 let event = ready!(self.registration.poll_write_ready(cx))?;
398
399 Poll::Ready(Ok(AsyncFdReadyGuard {
400 async_fd: self,
401 event: Some(event),
402 }))
403 }
404
405 /// Polls for write readiness.
406 ///
407 /// If the file descriptor is not currently ready for writing, this method
408 /// will store a clone of the [`Waker`] from the provided [`Context`]. When the
409 /// file descriptor becomes ready for writing, [`Waker::wake`] will be called.
410 ///
411 /// Note that on multiple calls to [`poll_write_ready`] or
412 /// [`poll_write_ready_mut`], only the `Waker` from the `Context` passed to the
413 /// most recent call is scheduled to receive a wakeup. (However,
414 /// [`poll_read_ready`] retains a second, independent waker).
415 ///
416 /// This method is intended for cases where creating and pinning a future
417 /// via [`writable`] is not feasible. Where possible, using [`writable`] is
418 /// preferred, as this supports polling from multiple tasks at once.
419 ///
420 /// This method takes `&mut self`, so it is possible to access the inner IO
421 /// resource mutably when handling the [`AsyncFdReadyMutGuard`].
422 ///
423 /// [`poll_read_ready`]: method@Self::poll_read_ready
424 /// [`poll_write_ready`]: method@Self::poll_write_ready
425 /// [`poll_write_ready_mut`]: method@Self::poll_write_ready_mut
426 /// [`writable`]: method@Self::readable
427 /// [`Context`]: struct@std::task::Context
428 /// [`Waker`]: struct@std::task::Waker
429 /// [`Waker::wake`]: method@std::task::Waker::wake
430 pub fn poll_write_ready_mut<'a>(
431 &'a mut self,
432 cx: &mut Context<'_>,
433 ) -> Poll<io::Result<AsyncFdReadyMutGuard<'a, T>>> {
434 let event = ready!(self.registration.poll_write_ready(cx))?;
435
436 Poll::Ready(Ok(AsyncFdReadyMutGuard {
437 async_fd: self,
438 event: Some(event),
439 }))
440 }
441
442 /// Waits for any of the requested ready states, returning a
443 /// [`AsyncFdReadyGuard`] that must be dropped to resume
444 /// polling for the requested ready states.
445 ///
446 /// The function may complete without the file descriptor being ready. This is a
447 /// false-positive and attempting an operation will return with
448 /// `io::ErrorKind::WouldBlock`. The function can also return with an empty
449 /// [`Ready`] set, so you should always check the returned value and possibly
450 /// wait again if the requested states are not set.
451 ///
452 /// When an IO operation does return `io::ErrorKind::WouldBlock`, the readiness must be cleared.
453 /// When a combined interest is used, it is important to clear only the readiness
454 /// that is actually observed to block. For instance when the combined
455 /// interest `Interest::READABLE | Interest::WRITABLE` is used, and a read blocks, only
456 /// read readiness should be cleared using the [`AsyncFdReadyGuard::clear_ready_matching`] method:
457 /// `guard.clear_ready_matching(Ready::READABLE)`.
458 /// Also clearing the write readiness in this case would be incorrect. The [`AsyncFdReadyGuard::clear_ready`]
459 /// method clears all readiness flags.
460 ///
461 /// This method takes `&self`, so it is possible to call this method
462 /// concurrently with other methods on this struct. This method only
463 /// provides shared access to the inner IO resource when handling the
464 /// [`AsyncFdReadyGuard`].
465 ///
466 /// # Examples
467 ///
468 /// Concurrently read and write to a [`std::net::TcpStream`] on the same task without
469 /// splitting.
470 ///
471 /// ```no_run
472 /// use std::error::Error;
473 /// use std::io;
474 /// use std::io::{Read, Write};
475 /// use std::net::TcpStream;
476 /// use tokio::io::unix::AsyncFd;
477 /// use tokio::io::{Interest, Ready};
478 ///
479 /// #[tokio::main]
480 /// async fn main() -> Result<(), Box<dyn Error>> {
481 /// let stream = TcpStream::connect("127.0.0.1:8080")?;
482 /// stream.set_nonblocking(true)?;
483 /// let stream = AsyncFd::new(stream)?;
484 ///
485 /// loop {
486 /// let mut guard = stream
487 /// .ready(Interest::READABLE | Interest::WRITABLE)
488 /// .await?;
489 ///
490 /// if guard.ready().is_readable() {
491 /// let mut data = vec![0; 1024];
492 /// // Try to read data, this may still fail with `WouldBlock`
493 /// // if the readiness event is a false positive.
494 /// match stream.get_ref().read(&mut data) {
495 /// Ok(n) => {
496 /// println!("read {} bytes", n);
497 /// }
498 /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
499 /// // a read has blocked, but a write might still succeed.
500 /// // clear only the read readiness.
501 /// guard.clear_ready_matching(Ready::READABLE);
502 /// continue;
503 /// }
504 /// Err(e) => {
505 /// return Err(e.into());
506 /// }
507 /// }
508 /// }
509 ///
510 /// if guard.ready().is_writable() {
511 /// // Try to write data, this may still fail with `WouldBlock`
512 /// // if the readiness event is a false positive.
513 /// match stream.get_ref().write(b"hello world") {
514 /// Ok(n) => {
515 /// println!("write {} bytes", n);
516 /// }
517 /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
518 /// // a write has blocked, but a read might still succeed.
519 /// // clear only the write readiness.
520 /// guard.clear_ready_matching(Ready::WRITABLE);
521 /// continue;
522 /// }
523 /// Err(e) => {
524 /// return Err(e.into());
525 /// }
526 /// }
527 /// }
528 /// }
529 /// }
530 /// ```
531 pub async fn ready(&self, interest: Interest) -> io::Result<AsyncFdReadyGuard<'_, T>> {
532 let event = self.registration.readiness(interest).await?;
533
534 Ok(AsyncFdReadyGuard {
535 async_fd: self,
536 event: Some(event),
537 })
538 }
539
540 /// Waits for any of the requested ready states, returning a
541 /// [`AsyncFdReadyMutGuard`] that must be dropped to resume
542 /// polling for the requested ready states.
543 ///
544 /// The function may complete without the file descriptor being ready. This is a
545 /// false-positive and attempting an operation will return with
546 /// `io::ErrorKind::WouldBlock`. The function can also return with an empty
547 /// [`Ready`] set, so you should always check the returned value and possibly
548 /// wait again if the requested states are not set.
549 ///
550 /// When an IO operation does return `io::ErrorKind::WouldBlock`, the readiness must be cleared.
551 /// When a combined interest is used, it is important to clear only the readiness
552 /// that is actually observed to block. For instance when the combined
553 /// interest `Interest::READABLE | Interest::WRITABLE` is used, and a read blocks, only
554 /// read readiness should be cleared using the [`AsyncFdReadyMutGuard::clear_ready_matching`] method:
555 /// `guard.clear_ready_matching(Ready::READABLE)`.
556 /// Also clearing the write readiness in this case would be incorrect.
557 /// The [`AsyncFdReadyMutGuard::clear_ready`] method clears all readiness flags.
558 ///
559 /// This method takes `&mut self`, so it is possible to access the inner IO
560 /// resource mutably when handling the [`AsyncFdReadyMutGuard`].
561 ///
562 /// # Examples
563 ///
564 /// Concurrently read and write to a [`std::net::TcpStream`] on the same task without
565 /// splitting.
566 ///
567 /// ```no_run
568 /// use std::error::Error;
569 /// use std::io;
570 /// use std::io::{Read, Write};
571 /// use std::net::TcpStream;
572 /// use tokio::io::unix::AsyncFd;
573 /// use tokio::io::{Interest, Ready};
574 ///
575 /// #[tokio::main]
576 /// async fn main() -> Result<(), Box<dyn Error>> {
577 /// let stream = TcpStream::connect("127.0.0.1:8080")?;
578 /// stream.set_nonblocking(true)?;
579 /// let mut stream = AsyncFd::new(stream)?;
580 ///
581 /// loop {
582 /// let mut guard = stream
583 /// .ready_mut(Interest::READABLE | Interest::WRITABLE)
584 /// .await?;
585 ///
586 /// if guard.ready().is_readable() {
587 /// let mut data = vec![0; 1024];
588 /// // Try to read data, this may still fail with `WouldBlock`
589 /// // if the readiness event is a false positive.
590 /// match guard.get_inner_mut().read(&mut data) {
591 /// Ok(n) => {
592 /// println!("read {} bytes", n);
593 /// }
594 /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
595 /// // a read has blocked, but a write might still succeed.
596 /// // clear only the read readiness.
597 /// guard.clear_ready_matching(Ready::READABLE);
598 /// continue;
599 /// }
600 /// Err(e) => {
601 /// return Err(e.into());
602 /// }
603 /// }
604 /// }
605 ///
606 /// if guard.ready().is_writable() {
607 /// // Try to write data, this may still fail with `WouldBlock`
608 /// // if the readiness event is a false positive.
609 /// match guard.get_inner_mut().write(b"hello world") {
610 /// Ok(n) => {
611 /// println!("write {} bytes", n);
612 /// }
613 /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
614 /// // a write has blocked, but a read might still succeed.
615 /// // clear only the write readiness.
616 /// guard.clear_ready_matching(Ready::WRITABLE);
617 /// continue;
618 /// }
619 /// Err(e) => {
620 /// return Err(e.into());
621 /// }
622 /// }
623 /// }
624 /// }
625 /// }
626 /// ```
627 pub async fn ready_mut(
628 &mut self,
629 interest: Interest,
630 ) -> io::Result<AsyncFdReadyMutGuard<'_, T>> {
631 let event = self.registration.readiness(interest).await?;
632
633 Ok(AsyncFdReadyMutGuard {
634 async_fd: self,
635 event: Some(event),
636 })
637 }
638
639 /// Waits for the file descriptor to become readable, returning a
640 /// [`AsyncFdReadyGuard`] that must be dropped to resume read-readiness
641 /// polling.
642 ///
643 /// This method takes `&self`, so it is possible to call this method
644 /// concurrently with other methods on this struct. This method only
645 /// provides shared access to the inner IO resource when handling the
646 /// [`AsyncFdReadyGuard`].
647 #[allow(clippy::needless_lifetimes)] // The lifetime improves rustdoc rendering.
648 pub async fn readable<'a>(&'a self) -> io::Result<AsyncFdReadyGuard<'a, T>> {
649 self.ready(Interest::READABLE).await
650 }
651
652 /// Waits for the file descriptor to become readable, returning a
653 /// [`AsyncFdReadyMutGuard`] that must be dropped to resume read-readiness
654 /// polling.
655 ///
656 /// This method takes `&mut self`, so it is possible to access the inner IO
657 /// resource mutably when handling the [`AsyncFdReadyMutGuard`].
658 #[allow(clippy::needless_lifetimes)] // The lifetime improves rustdoc rendering.
659 pub async fn readable_mut<'a>(&'a mut self) -> io::Result<AsyncFdReadyMutGuard<'a, T>> {
660 self.ready_mut(Interest::READABLE).await
661 }
662
663 /// Waits for the file descriptor to become writable, returning a
664 /// [`AsyncFdReadyGuard`] that must be dropped to resume write-readiness
665 /// polling.
666 ///
667 /// This method takes `&self`, so it is possible to call this method
668 /// concurrently with other methods on this struct. This method only
669 /// provides shared access to the inner IO resource when handling the
670 /// [`AsyncFdReadyGuard`].
671 #[allow(clippy::needless_lifetimes)] // The lifetime improves rustdoc rendering.
672 pub async fn writable<'a>(&'a self) -> io::Result<AsyncFdReadyGuard<'a, T>> {
673 self.ready(Interest::WRITABLE).await
674 }
675
676 /// Waits for the file descriptor to become writable, returning a
677 /// [`AsyncFdReadyMutGuard`] that must be dropped to resume write-readiness
678 /// polling.
679 ///
680 /// This method takes `&mut self`, so it is possible to access the inner IO
681 /// resource mutably when handling the [`AsyncFdReadyMutGuard`].
682 #[allow(clippy::needless_lifetimes)] // The lifetime improves rustdoc rendering.
683 pub async fn writable_mut<'a>(&'a mut self) -> io::Result<AsyncFdReadyMutGuard<'a, T>> {
684 self.ready_mut(Interest::WRITABLE).await
685 }
686
687 /// Reads or writes from the file descriptor using a user-provided IO operation.
688 ///
689 /// The `async_io` method is a convenience utility that waits for the file
690 /// descriptor to become ready, and then executes the provided IO operation.
691 /// Since file descriptors may be marked ready spuriously, the closure will
692 /// be called repeatedly until it returns something other than a
693 /// [`WouldBlock`] error. This is done using the following loop:
694 ///
695 /// ```no_run
696 /// # use std::io::{self, Result};
697 /// # struct Dox<T> { inner: T }
698 /// # impl<T> Dox<T> {
699 /// # async fn writable(&self) -> Result<&Self> {
700 /// # Ok(self)
701 /// # }
702 /// # fn try_io<R>(&self, _: impl FnMut(&T) -> Result<R>) -> Result<Result<R>> {
703 /// # panic!()
704 /// # }
705 /// async fn async_io<R>(&self, mut f: impl FnMut(&T) -> io::Result<R>) -> io::Result<R> {
706 /// loop {
707 /// // or `readable` if called with the read interest.
708 /// let guard = self.writable().await?;
709 ///
710 /// match guard.try_io(&mut f) {
711 /// Ok(result) => return result,
712 /// Err(_would_block) => continue,
713 /// }
714 /// }
715 /// }
716 /// # }
717 /// ```
718 ///
719 /// The closure should only return a [`WouldBlock`] error if it has performed
720 /// an IO operation on the file descriptor that failed due to the file descriptor not being
721 /// ready. Returning a [`WouldBlock`] error in any other situation will
722 /// incorrectly clear the readiness flag, which can cause the file descriptor to
723 /// behave incorrectly.
724 ///
725 /// The closure should not perform the IO operation using any of the methods
726 /// defined on the Tokio [`AsyncFd`] type, as this will mess with the
727 /// readiness flag and can cause the file descriptor to behave incorrectly.
728 ///
729 /// This method is not intended to be used with combined interests.
730 /// The closure should perform only one type of IO operation, so it should not
731 /// require more than one ready state. This method may panic or sleep forever
732 /// if it is called with a combined interest.
733 ///
734 /// # Examples
735 ///
736 /// This example sends some bytes on the inner [`std::net::UdpSocket`]. The `async_io`
737 /// method waits for readiness, and retries if the send operation does block. This example
738 /// is equivalent to the one given for [`try_io`].
739 ///
740 /// ```no_run
741 /// use tokio::io::{Interest, unix::AsyncFd};
742 ///
743 /// use std::io;
744 /// use std::net::UdpSocket;
745 ///
746 /// #[tokio::main]
747 /// async fn main() -> io::Result<()> {
748 /// let socket = UdpSocket::bind("0.0.0.0:8080")?;
749 /// socket.set_nonblocking(true)?;
750 /// let async_fd = AsyncFd::new(socket)?;
751 ///
752 /// let written = async_fd
753 /// .async_io(Interest::WRITABLE, |inner| inner.send(&[1, 2]))
754 /// .await?;
755 ///
756 /// println!("wrote {written} bytes");
757 ///
758 /// Ok(())
759 /// }
760 /// ```
761 ///
762 /// [`try_io`]: AsyncFdReadyGuard::try_io
763 /// [`WouldBlock`]: std::io::ErrorKind::WouldBlock
764 pub async fn async_io<R>(
765 &self,
766 interest: Interest,
767 mut f: impl FnMut(&T) -> io::Result<R>,
768 ) -> io::Result<R> {
769 self.registration
770 .async_io(interest, || f(self.get_ref()))
771 .await
772 }
773
774 /// Reads or writes from the file descriptor using a user-provided IO operation.
775 ///
776 /// The behavior is the same as [`async_io`], except that the closure can mutate the inner
777 /// value of the [`AsyncFd`].
778 ///
779 /// [`async_io`]: AsyncFd::async_io
780 pub async fn async_io_mut<R>(
781 &mut self,
782 interest: Interest,
783 mut f: impl FnMut(&mut T) -> io::Result<R>,
784 ) -> io::Result<R> {
785 self.registration
786 .async_io(interest, || f(self.inner.as_mut().unwrap()))
787 .await
788 }
789}
790
791impl<T: AsRawFd> AsRawFd for AsyncFd<T> {
792 fn as_raw_fd(&self) -> RawFd {
793 self.inner.as_ref().unwrap().as_raw_fd()
794 }
795}
796
797impl<T: AsRawFd> std::os::unix::io::AsFd for AsyncFd<T> {
798 fn as_fd(&self) -> std::os::unix::io::BorrowedFd<'_> {
799 unsafe { std::os::unix::io::BorrowedFd::borrow_raw(self.as_raw_fd()) }
800 }
801}
802
803impl<T: std::fmt::Debug + AsRawFd> std::fmt::Debug for AsyncFd<T> {
804 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
805 f.debug_struct("AsyncFd")
806 .field("inner", &self.inner)
807 .finish()
808 }
809}
810
811impl<T: AsRawFd> Drop for AsyncFd<T> {
812 fn drop(&mut self) {
813 let _ = self.take_inner();
814 }
815}
816
817impl<'a, Inner: AsRawFd> AsyncFdReadyGuard<'a, Inner> {
818 /// Indicates to tokio that the file descriptor is no longer ready. All
819 /// internal readiness flags will be cleared, and tokio will wait for the
820 /// next edge-triggered readiness notification from the OS.
821 ///
822 /// This function is commonly used with guards returned by [`AsyncFd::readable`] and
823 /// [`AsyncFd::writable`].
824 ///
825 /// It is critical that this function not be called unless your code
826 /// _actually observes_ that the file descriptor is _not_ ready. Do not call
827 /// it simply because, for example, a read succeeded; it should be called
828 /// when a read is observed to block.
829 pub fn clear_ready(&mut self) {
830 if let Some(event) = self.event.take() {
831 self.async_fd.registration.clear_readiness(event);
832 }
833 }
834
835 /// Indicates to tokio that the file descriptor no longer has a specific readiness.
836 /// The internal readiness flag will be cleared, and tokio will wait for the
837 /// next edge-triggered readiness notification from the OS.
838 ///
839 /// This function is useful in combination with the [`AsyncFd::ready`] method when a
840 /// combined interest like `Interest::READABLE | Interest::WRITABLE` is used.
841 ///
842 /// It is critical that this function not be called unless your code
843 /// _actually observes_ that the file descriptor is _not_ ready for the provided `Ready`.
844 /// Do not call it simply because, for example, a read succeeded; it should be called
845 /// when a read is observed to block. Only clear the specific readiness that is observed to
846 /// block. For example when a read blocks when using a combined interest,
847 /// only clear `Ready::READABLE`.
848 ///
849 /// # Examples
850 ///
851 /// Concurrently read and write to a [`std::net::TcpStream`] on the same task without
852 /// splitting.
853 ///
854 /// ```no_run
855 /// use std::error::Error;
856 /// use std::io;
857 /// use std::io::{Read, Write};
858 /// use std::net::TcpStream;
859 /// use tokio::io::unix::AsyncFd;
860 /// use tokio::io::{Interest, Ready};
861 ///
862 /// #[tokio::main]
863 /// async fn main() -> Result<(), Box<dyn Error>> {
864 /// let stream = TcpStream::connect("127.0.0.1:8080")?;
865 /// stream.set_nonblocking(true)?;
866 /// let stream = AsyncFd::new(stream)?;
867 ///
868 /// loop {
869 /// let mut guard = stream
870 /// .ready(Interest::READABLE | Interest::WRITABLE)
871 /// .await?;
872 ///
873 /// if guard.ready().is_readable() {
874 /// let mut data = vec![0; 1024];
875 /// // Try to read data, this may still fail with `WouldBlock`
876 /// // if the readiness event is a false positive.
877 /// match stream.get_ref().read(&mut data) {
878 /// Ok(n) => {
879 /// println!("read {} bytes", n);
880 /// }
881 /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
882 /// // a read has blocked, but a write might still succeed.
883 /// // clear only the read readiness.
884 /// guard.clear_ready_matching(Ready::READABLE);
885 /// continue;
886 /// }
887 /// Err(e) => {
888 /// return Err(e.into());
889 /// }
890 /// }
891 /// }
892 ///
893 /// if guard.ready().is_writable() {
894 /// // Try to write data, this may still fail with `WouldBlock`
895 /// // if the readiness event is a false positive.
896 /// match stream.get_ref().write(b"hello world") {
897 /// Ok(n) => {
898 /// println!("write {} bytes", n);
899 /// }
900 /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
901 /// // a write has blocked, but a read might still succeed.
902 /// // clear only the write readiness.
903 /// guard.clear_ready_matching(Ready::WRITABLE);
904 /// continue;
905 /// }
906 /// Err(e) => {
907 /// return Err(e.into());
908 /// }
909 /// }
910 /// }
911 /// }
912 /// }
913 /// ```
914 pub fn clear_ready_matching(&mut self, ready: Ready) {
915 if let Some(mut event) = self.event.take() {
916 self.async_fd
917 .registration
918 .clear_readiness(event.with_ready(ready));
919
920 // the event is no longer ready for the readiness that was just cleared
921 event.ready = event.ready - ready;
922
923 if !event.ready.is_empty() {
924 self.event = Some(event);
925 }
926 }
927 }
928
929 /// This method should be invoked when you intentionally want to keep the
930 /// ready flag asserted.
931 ///
932 /// While this function is itself a no-op, it satisfies the `#[must_use]`
933 /// constraint on the [`AsyncFdReadyGuard`] type.
934 pub fn retain_ready(&mut self) {
935 // no-op
936 }
937
938 /// Get the [`Ready`] value associated with this guard.
939 ///
940 /// This method will return the empty readiness state if
941 /// [`AsyncFdReadyGuard::clear_ready`] has been called on
942 /// the guard.
943 ///
944 /// [`Ready`]: crate::io::Ready
945 pub fn ready(&self) -> Ready {
946 match &self.event {
947 Some(event) => event.ready,
948 None => Ready::EMPTY,
949 }
950 }
951
952 /// Performs the provided IO operation.
953 ///
954 /// If `f` returns a [`WouldBlock`] error, the readiness state associated
955 /// with this file descriptor is cleared, and the method returns
956 /// `Err(TryIoError::WouldBlock)`. You will typically need to poll the
957 /// `AsyncFd` again when this happens.
958 ///
959 /// This method helps ensure that the readiness state of the underlying file
960 /// descriptor remains in sync with the tokio-side readiness state, by
961 /// clearing the tokio-side state only when a [`WouldBlock`] condition
962 /// occurs. It is the responsibility of the caller to ensure that `f`
963 /// returns [`WouldBlock`] only if the file descriptor that originated this
964 /// `AsyncFdReadyGuard` no longer expresses the readiness state that was queried to
965 /// create this `AsyncFdReadyGuard`.
966 ///
967 /// # Examples
968 ///
969 /// This example sends some bytes to the inner [`std::net::UdpSocket`]. Waiting
970 /// for write-readiness and retrying when the send operation does block are explicit.
971 /// This example can be written more succinctly using [`AsyncFd::async_io`].
972 ///
973 /// ```no_run
974 /// use tokio::io::unix::AsyncFd;
975 ///
976 /// use std::io;
977 /// use std::net::UdpSocket;
978 ///
979 /// #[tokio::main]
980 /// async fn main() -> io::Result<()> {
981 /// let socket = UdpSocket::bind("0.0.0.0:8080")?;
982 /// socket.set_nonblocking(true)?;
983 /// let async_fd = AsyncFd::new(socket)?;
984 ///
985 /// let written = loop {
986 /// let mut guard = async_fd.writable().await?;
987 /// match guard.try_io(|inner| inner.get_ref().send(&[1, 2])) {
988 /// Ok(result) => {
989 /// break result?;
990 /// }
991 /// Err(_would_block) => {
992 /// // try_io already cleared the file descriptor's readiness state
993 /// continue;
994 /// }
995 /// }
996 /// };
997 ///
998 /// println!("wrote {written} bytes");
999 ///
1000 /// Ok(())
1001 /// }
1002 /// ```
1003 ///
1004 /// [`WouldBlock`]: std::io::ErrorKind::WouldBlock
1005 // Alias for old name in 0.x
1006 #[cfg_attr(docsrs, doc(alias = "with_io"))]
1007 pub fn try_io<R>(
1008 &mut self,
1009 f: impl FnOnce(&'a AsyncFd<Inner>) -> io::Result<R>,
1010 ) -> Result<io::Result<R>, TryIoError> {
1011 let result = f(self.async_fd);
1012
1013 match result {
1014 Err(err) if err.kind() == io::ErrorKind::WouldBlock => {
1015 self.clear_ready();
1016 Err(TryIoError(()))
1017 }
1018 result => Ok(result),
1019 }
1020 }
1021
1022 /// Returns a shared reference to the inner [`AsyncFd`].
1023 pub fn get_ref(&self) -> &'a AsyncFd<Inner> {
1024 self.async_fd
1025 }
1026
1027 /// Returns a shared reference to the backing object of the inner [`AsyncFd`].
1028 pub fn get_inner(&self) -> &'a Inner {
1029 self.get_ref().get_ref()
1030 }
1031}
1032
1033impl<'a, Inner: AsRawFd> AsyncFdReadyMutGuard<'a, Inner> {
1034 /// Indicates to tokio that the file descriptor is no longer ready. All
1035 /// internal readiness flags will be cleared, and tokio will wait for the
1036 /// next edge-triggered readiness notification from the OS.
1037 ///
1038 /// This function is commonly used with guards returned by [`AsyncFd::readable_mut`] and
1039 /// [`AsyncFd::writable_mut`].
1040 ///
1041 /// It is critical that this function not be called unless your code
1042 /// _actually observes_ that the file descriptor is _not_ ready. Do not call
1043 /// it simply because, for example, a read succeeded; it should be called
1044 /// when a read is observed to block.
1045 pub fn clear_ready(&mut self) {
1046 if let Some(event) = self.event.take() {
1047 self.async_fd.registration.clear_readiness(event);
1048 }
1049 }
1050
1051 /// Indicates to tokio that the file descriptor no longer has a specific readiness.
1052 /// The internal readiness flag will be cleared, and tokio will wait for the
1053 /// next edge-triggered readiness notification from the OS.
1054 ///
1055 /// This function is useful in combination with the [`AsyncFd::ready_mut`] method when a
1056 /// combined interest like `Interest::READABLE | Interest::WRITABLE` is used.
1057 ///
1058 /// It is critical that this function not be called unless your code
1059 /// _actually observes_ that the file descriptor is _not_ ready for the provided `Ready`.
1060 /// Do not call it simply because, for example, a read succeeded; it should be called
1061 /// when a read is observed to block. Only clear the specific readiness that is observed to
1062 /// block. For example when a read blocks when using a combined interest,
1063 /// only clear `Ready::READABLE`.
1064 ///
1065 /// # Examples
1066 ///
1067 /// Concurrently read and write to a [`std::net::TcpStream`] on the same task without
1068 /// splitting.
1069 ///
1070 /// ```no_run
1071 /// use std::error::Error;
1072 /// use std::io;
1073 /// use std::io::{Read, Write};
1074 /// use std::net::TcpStream;
1075 /// use tokio::io::unix::AsyncFd;
1076 /// use tokio::io::{Interest, Ready};
1077 ///
1078 /// #[tokio::main]
1079 /// async fn main() -> Result<(), Box<dyn Error>> {
1080 /// let stream = TcpStream::connect("127.0.0.1:8080")?;
1081 /// stream.set_nonblocking(true)?;
1082 /// let mut stream = AsyncFd::new(stream)?;
1083 ///
1084 /// loop {
1085 /// let mut guard = stream
1086 /// .ready_mut(Interest::READABLE | Interest::WRITABLE)
1087 /// .await?;
1088 ///
1089 /// if guard.ready().is_readable() {
1090 /// let mut data = vec![0; 1024];
1091 /// // Try to read data, this may still fail with `WouldBlock`
1092 /// // if the readiness event is a false positive.
1093 /// match guard.get_inner_mut().read(&mut data) {
1094 /// Ok(n) => {
1095 /// println!("read {} bytes", n);
1096 /// }
1097 /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
1098 /// // a read has blocked, but a write might still succeed.
1099 /// // clear only the read readiness.
1100 /// guard.clear_ready_matching(Ready::READABLE);
1101 /// continue;
1102 /// }
1103 /// Err(e) => {
1104 /// return Err(e.into());
1105 /// }
1106 /// }
1107 /// }
1108 ///
1109 /// if guard.ready().is_writable() {
1110 /// // Try to write data, this may still fail with `WouldBlock`
1111 /// // if the readiness event is a false positive.
1112 /// match guard.get_inner_mut().write(b"hello world") {
1113 /// Ok(n) => {
1114 /// println!("write {} bytes", n);
1115 /// }
1116 /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
1117 /// // a write has blocked, but a read might still succeed.
1118 /// // clear only the write readiness.
1119 /// guard.clear_ready_matching(Ready::WRITABLE);
1120 /// continue;
1121 /// }
1122 /// Err(e) => {
1123 /// return Err(e.into());
1124 /// }
1125 /// }
1126 /// }
1127 /// }
1128 /// }
1129 /// ```
1130 pub fn clear_ready_matching(&mut self, ready: Ready) {
1131 if let Some(mut event) = self.event.take() {
1132 self.async_fd
1133 .registration
1134 .clear_readiness(event.with_ready(ready));
1135
1136 // the event is no longer ready for the readiness that was just cleared
1137 event.ready = event.ready - ready;
1138
1139 if !event.ready.is_empty() {
1140 self.event = Some(event);
1141 }
1142 }
1143 }
1144
1145 /// This method should be invoked when you intentionally want to keep the
1146 /// ready flag asserted.
1147 ///
1148 /// While this function is itself a no-op, it satisfies the `#[must_use]`
1149 /// constraint on the [`AsyncFdReadyGuard`] type.
1150 pub fn retain_ready(&mut self) {
1151 // no-op
1152 }
1153
1154 /// Get the [`Ready`] value associated with this guard.
1155 ///
1156 /// This method will return the empty readiness state if
1157 /// [`AsyncFdReadyGuard::clear_ready`] has been called on
1158 /// the guard.
1159 ///
1160 /// [`Ready`]: super::Ready
1161 pub fn ready(&self) -> Ready {
1162 match &self.event {
1163 Some(event) => event.ready,
1164 None => Ready::EMPTY,
1165 }
1166 }
1167
1168 /// Performs the provided IO operation.
1169 ///
1170 /// If `f` returns a [`WouldBlock`] error, the readiness state associated
1171 /// with this file descriptor is cleared, and the method returns
1172 /// `Err(TryIoError::WouldBlock)`. You will typically need to poll the
1173 /// `AsyncFd` again when this happens.
1174 ///
1175 /// This method helps ensure that the readiness state of the underlying file
1176 /// descriptor remains in sync with the tokio-side readiness state, by
1177 /// clearing the tokio-side state only when a [`WouldBlock`] condition
1178 /// occurs. It is the responsibility of the caller to ensure that `f`
1179 /// returns [`WouldBlock`] only if the file descriptor that originated this
1180 /// `AsyncFdReadyGuard` no longer expresses the readiness state that was queried to
1181 /// create this `AsyncFdReadyGuard`.
1182 ///
1183 /// [`WouldBlock`]: std::io::ErrorKind::WouldBlock
1184 pub fn try_io<R>(
1185 &mut self,
1186 f: impl FnOnce(&mut AsyncFd<Inner>) -> io::Result<R>,
1187 ) -> Result<io::Result<R>, TryIoError> {
1188 let result = f(self.async_fd);
1189
1190 match result {
1191 Err(err) if err.kind() == io::ErrorKind::WouldBlock => {
1192 self.clear_ready();
1193 Err(TryIoError(()))
1194 }
1195 result => Ok(result),
1196 }
1197 }
1198
1199 /// Returns a shared reference to the inner [`AsyncFd`].
1200 pub fn get_ref(&self) -> &AsyncFd<Inner> {
1201 self.async_fd
1202 }
1203
1204 /// Returns a mutable reference to the inner [`AsyncFd`].
1205 pub fn get_mut(&mut self) -> &mut AsyncFd<Inner> {
1206 self.async_fd
1207 }
1208
1209 /// Returns a shared reference to the backing object of the inner [`AsyncFd`].
1210 pub fn get_inner(&self) -> &Inner {
1211 self.get_ref().get_ref()
1212 }
1213
1214 /// Returns a mutable reference to the backing object of the inner [`AsyncFd`].
1215 pub fn get_inner_mut(&mut self) -> &mut Inner {
1216 self.get_mut().get_mut()
1217 }
1218}
1219
1220impl<'a, T: std::fmt::Debug + AsRawFd> std::fmt::Debug for AsyncFdReadyGuard<'a, T> {
1221 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1222 f.debug_struct("ReadyGuard")
1223 .field("async_fd", &self.async_fd)
1224 .finish()
1225 }
1226}
1227
1228impl<'a, T: std::fmt::Debug + AsRawFd> std::fmt::Debug for AsyncFdReadyMutGuard<'a, T> {
1229 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1230 f.debug_struct("MutReadyGuard")
1231 .field("async_fd", &self.async_fd)
1232 .finish()
1233 }
1234}
1235
1236/// The error type returned by [`try_io`].
1237///
1238/// This error indicates that the IO resource returned a [`WouldBlock`] error.
1239///
1240/// [`WouldBlock`]: std::io::ErrorKind::WouldBlock
1241/// [`try_io`]: method@AsyncFdReadyGuard::try_io
1242#[derive(Debug)]
1243pub struct TryIoError(());
1244