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