      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    379
    380
    381
    382
    383
    384
    385
    386
    387
    388
    389
    390
    391
    392
    393
    394
    395
    396
    397
    398
    399
    400
    401
    402
    403
    404
    405
    406
    407
    408
    409
    410
    411
    412
    413
    414
    415
    416
    417
    418
    419
    420
    421
    422
    423
    424
    425
    426
    427
    428
    429
    430
    431
    432
    433
    434
    435
    436
    437
    438
    439
    440
    441
    442
    443
    444
    445
    446
    447
    448
    449
    450
    451
    452
    453
    454
    455
    456
    457
    458
    459
    460
    461
    462
    463
    464
    465
    466
    467
    468
    469
    470
    471
    472
    473
    474
    475
    476
    477
    478
    479
    480
    481
    482
    483
    484
    485
    486
    487
    488
    489
    490
    491
    492
    493
    494
    495
    496
    497
    498
    499
    500
    501
    502
    503
    504
    505
    506
    507
    508
    509
    510
    511
    512
    513
    514
    515
    516
    517
    518
    519
    520
    521
    522
    523
    524
    525
    526
    527
    528
    529
    530
    531
    532
    533
    534
    535
    536
    537
    538
    539
    540
    541
    542
    543
    544
    545
    546
    547
    548
    549
    550
    551
    552
    553
    554
    555
    556
    557
    558
    559
    560
    561
    562
    563
    564
    565
    566
    567
    568
    569
    570
    571
    572
    573
    574
    575
    576
    577
    578
    579
    580
    581
    582
    583
    584
    585
    586
    587
    588
    589
    590
    591
    592
    593
    594
    595
    596
    597
    598
    599
    600
    601
    602
    603
    604
    605
    606
    607
    608
    609
    610
    611
    612
    613
    614
    615
    616
    617
    618
    619
    620
    621
    622
    623
    624
    625
    626
    627

    use crate::io::driver::{Handle, Interest, ReadyEvent, Registration};

    use mio::unix::SourceFd;
    use std::io;
    use std::os::unix::io::{AsRawFd, RawFd};
    use std::{task::Context, task::Poll};

    /// Associates an IO object backed by a Unix file descriptor with the tokio
    /// reactor, allowing for readiness to be polled. The file descriptor must be of
    /// a type that can be used with the OS polling facilities (ie, `poll`, `epoll`,
    /// `kqueue`, etc), such as a network socket or pipe.
    ///
    /// Creating an AsyncFd registers the file descriptor with the current tokio
    /// Reactor, allowing you to directly await the file descriptor being readable
    /// or writable. Once registered, the file descriptor remains registered until
    /// the AsyncFd is dropped.
    ///
    /// The AsyncFd takes ownership of an arbitrary object to represent the IO
    /// object. It is intended that this object will handle closing the file
    /// descriptor when it is dropped, avoiding resource leaks and ensuring that the
    /// AsyncFd can clean up the registration before closing the file descriptor.
    /// The [`AsyncFd::into_inner`] function can be used to extract the inner object
    /// to retake control from the tokio IO reactor.
    ///
    /// The inner object is required to implement [`AsRawFd`]. This file descriptor
    /// must not change while [`AsyncFd`] owns the inner object, i.e. the
    /// [`AsRawFd::as_raw_fd`] method on the inner type must always return the same
    /// file descriptor when called multiple times. Failure to uphold this results
    /// in unspecified behavior in the IO driver, which may include breaking
    /// notifications for other sockets/etc.
    ///
    /// Polling for readiness is done by calling the async functions [`readable`]
    /// and [`writable`]. These functions complete when the associated readiness
    /// condition is observed. Any number of tasks can query the same `AsyncFd` in
    /// parallel, on the same or different conditions.
    ///
    /// On some platforms, the readiness detecting mechanism relies on
    /// edge-triggered notifications. This means that the OS will only notify Tokio
    /// when the file descriptor transitions from not-ready to ready. Tokio
    /// internally tracks when it has received a ready notification, and when
    /// readiness checking functions like [`readable`] and [`writable`] are called,
    /// if the readiness flag is set, these async functions will complete
    /// immediately.
    ///
    /// This however does mean that it is critical to ensure that this ready flag is
    /// cleared when (and only when) the file descriptor ceases to be ready. The
    /// [`AsyncFdReadyGuard`] returned from readiness checking functions serves this
    /// function; after calling a readiness-checking async function, you must use
    /// this [`AsyncFdReadyGuard`] to signal to tokio whether the file descriptor is no
    /// longer in a ready state.
    ///
    /// ## Use with to a poll-based API
    ///
    /// In some cases it may be desirable to use `AsyncFd` from APIs similar to
    /// [`TcpStream::poll_read_ready`]. The [`AsyncFd::poll_read_ready`] and
    /// [`AsyncFd::poll_write_ready`] functions are provided for this purpose.
    /// Because these functions don't create a future to hold their state, they have
    /// the limitation that only one task can wait on each direction (read or write)
    /// at a time.
    ///
    /// # Examples
    ///
    /// This example shows how to turn [`std::net::TcpStream`] asynchronous using
    /// `AsyncFd`.  It implements `read` as an async fn, and `AsyncWrite` as a trait
    /// to show how to implement both approaches.
    ///
    /// ```no_run
    /// use futures::ready;
    /// use std::io::{self, Read, Write};
    /// use std::net::TcpStream;
    /// use std::pin::Pin;
    /// use std::task::{Context, Poll};
    /// use tokio::io::AsyncWrite;
    /// use tokio::io::unix::AsyncFd;
    ///
    /// pub struct AsyncTcpStream {
    ///     inner: AsyncFd<TcpStream>,
    /// }
    ///
    /// impl AsyncTcpStream {
    ///     pub fn new(tcp: TcpStream) -> io::Result<Self> {
    ///         Ok(Self {
    ///             inner: AsyncFd::new(tcp)?,
    ///         })
    ///     }
    ///
    ///     pub async fn read(&self, out: &mut [u8]) -> io::Result<usize> {
    ///         loop {
    ///             let mut guard = self.inner.readable().await?;
    ///
    ///             match guard.try_io(|inner| inner.get_ref().read(out)) {
    ///                 Ok(result) => return result,
    ///                 Err(_would_block) => continue,
    ///             }
    ///         }
    ///     }
    /// }
    ///
    /// impl AsyncWrite for AsyncTcpStream {
    ///     fn poll_write(
    ///         self: Pin<&mut Self>,
    ///         cx: &mut Context<'_>,
    ///         buf: &[u8]
    ///     ) -> Poll<io::Result<usize>> {
    ///         loop {
    ///             let mut guard = ready!(self.inner.poll_write_ready(cx))?;
    ///
    ///             match guard.try_io(|inner| inner.get_ref().write(buf)) {
    ///                 Ok(result) => return Poll::Ready(result),
    ///                 Err(_would_block) => continue,
    ///             }
    ///         }
    ///     }
    ///
    ///     fn poll_flush(
    ///         self: Pin<&mut Self>,
    ///         cx: &mut Context<'_>,
    ///     ) -> Poll<io::Result<()>> {
    ///         // tcp flush is a no-op
    ///         Poll::Ready(Ok(()))
    ///     }
    ///
    ///     fn poll_shutdown(
    ///         self: Pin<&mut Self>,
    ///         cx: &mut Context<'_>,
    ///     ) -> Poll<io::Result<()>> {
    ///         self.inner.get_ref().shutdown(std::net::Shutdown::Write)?;
    ///         Poll::Ready(Ok(()))
    ///     }
    /// }
    /// ```
    ///
    /// [`readable`]: method@Self::readable
    /// [`writable`]: method@Self::writable
    /// [`AsyncFdReadyGuard`]: struct@self::AsyncFdReadyGuard
    /// [`TcpStream::poll_read_ready`]: struct@crate::net::TcpStream
    pub struct AsyncFd<T: AsRawFd> {
        registration: Registration,
        inner: Option<T>,
    }

    /// Represents an IO-ready event detected on a particular file descriptor that
    /// has not yet been acknowledged. This is a `must_use` structure to help ensure
    /// that you do not forget to explicitly clear (or not clear) the event.
    ///
    /// This type exposes an immutable reference to the underlying IO object.
    #[must_use = "You must explicitly choose whether to clear the readiness state by calling a method on ReadyGuard"]
    pub struct AsyncFdReadyGuard<'a, T: AsRawFd> {
        async_fd: &'a AsyncFd<T>,
        event: Option<ReadyEvent>,
    }

    /// Represents an IO-ready event detected on a particular file descriptor that
    /// has not yet been acknowledged. This is a `must_use` structure to help ensure
    /// that you do not forget to explicitly clear (or not clear) the event.
    ///
    /// This type exposes a mutable reference to the underlying IO object.
    #[must_use = "You must explicitly choose whether to clear the readiness state by calling a method on ReadyGuard"]
    pub struct AsyncFdReadyMutGuard<'a, T: AsRawFd> {
        async_fd: &'a mut AsyncFd<T>,
        event: Option<ReadyEvent>,
    }

    const ALL_INTEREST: Interest = Interest::READABLE.add(Interest::WRITABLE);

    impl<T: AsRawFd> AsyncFd<T> {
        #[inline]
        /// Creates an AsyncFd backed by (and taking ownership of) an object
        /// implementing [`AsRawFd`]. The backing file descriptor is cached at the
        /// time of creation.
        ///
        /// This method must be called in the context of a tokio runtime.
        pub fn new(inner: T) -> io::Result<Self>
        where
            T: AsRawFd,
        {
            Self::with_interest(inner, ALL_INTEREST)
        }

        #[inline]
        /// Creates new instance as `new` with additional ability to customize interest,
        /// allowing to specify whether file descriptor will be polled for read, write or both.
        pub fn with_interest(inner: T, interest: Interest) -> io::Result<Self>
        where
            T: AsRawFd,
        {
            Self::new_with_handle_and_interest(inner, Handle::current(), interest)
        }

        pub(crate) fn new_with_handle_and_interest(
            inner: T,
            handle: Handle,
            interest: Interest,
        ) -> io::Result<Self> {
            let fd = inner.as_raw_fd();

            let registration =
                Registration::new_with_interest_and_handle(&mut SourceFd(&fd), interest, handle)?;

            Ok(AsyncFd {
                registration,
                inner: Some(inner),
            })
        }

        /// Returns a shared reference to the backing object of this [`AsyncFd`]
        #[inline]
        pub fn get_ref(&self) -> &T {
            self.inner.as_ref().unwrap()
        }

        /// Returns a mutable reference to the backing object of this [`AsyncFd`]
        #[inline]
        pub fn get_mut(&mut self) -> &mut T {
            self.inner.as_mut().unwrap()
        }

        fn take_inner(&mut self) -> Option<T> {
            let fd = self.inner.as_ref().map(AsRawFd::as_raw_fd);

            if let Some(fd) = fd {
                let _ = self.registration.deregister(&mut SourceFd(&fd));
            }

            self.inner.take()
        }

        /// Deregisters this file descriptor and returns ownership of the backing
        /// object.
        pub fn into_inner(mut self) -> T {
            self.take_inner().unwrap()
        }

        /// Polls for read readiness.
        ///
        /// If the file descriptor is not currently ready for reading, this method
        /// will store a clone of the [`Waker`] from the provided [`Context`]. When the
        /// file descriptor becomes ready for reading, [`Waker::wake`] will be called.
        ///
        /// Note that on multiple calls to [`poll_read_ready`] or
        /// [`poll_read_ready_mut`], only the `Waker` from the `Context` passed to the
        /// most recent call is scheduled to receive a wakeup. (However,
        /// [`poll_write_ready`] retains a second, independent waker).
        ///
        /// This method is intended for cases where creating and pinning a future
        /// via [`readable`] is not feasible. Where possible, using [`readable`] is
        /// preferred, as this supports polling from multiple tasks at once.
        ///
        /// This method takes `&self`, so it is possible to call this method
        /// concurrently with other methods on this struct. This method only
        /// provides shared access to the inner IO resource when handling the
        /// [`AsyncFdReadyGuard`].
        ///
        /// [`poll_read_ready`]: method@Self::poll_read_ready
        /// [`poll_read_ready_mut`]: method@Self::poll_read_ready_mut
        /// [`poll_write_ready`]: method@Self::poll_write_ready
        /// [`readable`]: method@Self::readable
        /// [`Context`]: struct@std::task::Context
        /// [`Waker`]: struct@std::task::Waker
        /// [`Waker::wake`]: method@std::task::Waker::wake
        pub fn poll_read_ready<'a>(
            &'a self,
            cx: &mut Context<'_>,
        ) -> Poll<io::Result<AsyncFdReadyGuard<'a, T>>> {
            let event = ready!(self.registration.poll_read_ready(cx))?;

            Ok(AsyncFdReadyGuard {
                async_fd: self,
                event: Some(event),
            })
            .into()
        }

        /// Polls for read readiness.
        ///
        /// If the file descriptor is not currently ready for reading, this method
        /// will store a clone of the [`Waker`] from the provided [`Context`]. When the
        /// file descriptor becomes ready for reading, [`Waker::wake`] will be called.
        ///
        /// Note that on multiple calls to [`poll_read_ready`] or
        /// [`poll_read_ready_mut`], only the `Waker` from the `Context` passed to the
        /// most recent call is scheduled to receive a wakeup. (However,
        /// [`poll_write_ready`] retains a second, independent waker).
        ///
        /// This method is intended for cases where creating and pinning a future
        /// via [`readable`] is not feasible. Where possible, using [`readable`] is
        /// preferred, as this supports polling from multiple tasks at once.
        ///
        /// This method takes `&mut self`, so it is possible to access the inner IO
        /// resource mutably when handling the [`AsyncFdReadyMutGuard`].
        ///
        /// [`poll_read_ready`]: method@Self::poll_read_ready
        /// [`poll_read_ready_mut`]: method@Self::poll_read_ready_mut
        /// [`poll_write_ready`]: method@Self::poll_write_ready
        /// [`readable`]: method@Self::readable
        /// [`Context`]: struct@std::task::Context
        /// [`Waker`]: struct@std::task::Waker
        /// [`Waker::wake`]: method@std::task::Waker::wake
        pub fn poll_read_ready_mut<'a>(
            &'a mut self,
            cx: &mut Context<'_>,
        ) -> Poll<io::Result<AsyncFdReadyMutGuard<'a, T>>> {
            let event = ready!(self.registration.poll_read_ready(cx))?;

            Ok(AsyncFdReadyMutGuard {
                async_fd: self,
                event: Some(event),
            })
            .into()
        }

        /// Polls for write readiness.
        ///
        /// If the file descriptor is not currently ready for writing, this method
        /// will store a clone of the [`Waker`] from the provided [`Context`]. When the
        /// file descriptor becomes ready for writing, [`Waker::wake`] will be called.
        ///
        /// Note that on multiple calls to [`poll_write_ready`] or
        /// [`poll_write_ready_mut`], only the `Waker` from the `Context` passed to the
        /// most recent call is scheduled to receive a wakeup. (However,
        /// [`poll_read_ready`] retains a second, independent waker).
        ///
        /// This method is intended for cases where creating and pinning a future
        /// via [`writable`] is not feasible. Where possible, using [`writable`] is
        /// preferred, as this supports polling from multiple tasks at once.
        ///
        /// This method takes `&self`, so it is possible to call this method
        /// concurrently with other methods on this struct. This method only
        /// provides shared access to the inner IO resource when handling the
        /// [`AsyncFdReadyGuard`].
        ///
        /// [`poll_read_ready`]: method@Self::poll_read_ready
        /// [`poll_write_ready`]: method@Self::poll_write_ready
        /// [`poll_write_ready_mut`]: method@Self::poll_write_ready_mut
        /// [`writable`]: method@Self::readable
        /// [`Context`]: struct@std::task::Context
        /// [`Waker`]: struct@std::task::Waker
        /// [`Waker::wake`]: method@std::task::Waker::wake
        pub fn poll_write_ready<'a>(
            &'a self,
            cx: &mut Context<'_>,
        ) -> Poll<io::Result<AsyncFdReadyGuard<'a, T>>> {
            let event = ready!(self.registration.poll_write_ready(cx))?;

            Ok(AsyncFdReadyGuard {
                async_fd: self,
                event: Some(event),
            })
            .into()
        }

        /// Polls for write readiness.
        ///
        /// If the file descriptor is not currently ready for writing, this method
        /// will store a clone of the [`Waker`] from the provided [`Context`]. When the
        /// file descriptor becomes ready for writing, [`Waker::wake`] will be called.
        ///
        /// Note that on multiple calls to [`poll_write_ready`] or
        /// [`poll_write_ready_mut`], only the `Waker` from the `Context` passed to the
        /// most recent call is scheduled to receive a wakeup. (However,
        /// [`poll_read_ready`] retains a second, independent waker).
        ///
        /// This method is intended for cases where creating and pinning a future
        /// via [`writable`] is not feasible. Where possible, using [`writable`] is
        /// preferred, as this supports polling from multiple tasks at once.
        ///
        /// This method takes `&mut self`, so it is possible to access the inner IO
        /// resource mutably when handling the [`AsyncFdReadyMutGuard`].
        ///
        /// [`poll_read_ready`]: method@Self::poll_read_ready
        /// [`poll_write_ready`]: method@Self::poll_write_ready
        /// [`poll_write_ready_mut`]: method@Self::poll_write_ready_mut
        /// [`writable`]: method@Self::readable
        /// [`Context`]: struct@std::task::Context
        /// [`Waker`]: struct@std::task::Waker
        /// [`Waker::wake`]: method@std::task::Waker::wake
        pub fn poll_write_ready_mut<'a>(
            &'a mut self,
            cx: &mut Context<'_>,
        ) -> Poll<io::Result<AsyncFdReadyMutGuard<'a, T>>> {
            let event = ready!(self.registration.poll_write_ready(cx))?;

            Ok(AsyncFdReadyMutGuard {
                async_fd: self,
                event: Some(event),
            })
            .into()
        }

        async fn readiness(&self, interest: Interest) -> io::Result<AsyncFdReadyGuard<'_, T>> {
            let event = self.registration.readiness(interest).await?;

            Ok(AsyncFdReadyGuard {
                async_fd: self,
                event: Some(event),
            })
        }

        async fn readiness_mut(
            &mut self,
            interest: Interest,
        ) -> io::Result<AsyncFdReadyMutGuard<'_, T>> {
            let event = self.registration.readiness(interest).await?;

            Ok(AsyncFdReadyMutGuard {
                async_fd: self,
                event: Some(event),
            })
        }

        /// Waits for the file descriptor to become readable, returning a
        /// [`AsyncFdReadyGuard`] that must be dropped to resume read-readiness
        /// polling.
        ///
        /// This method takes `&self`, so it is possible to call this method
        /// concurrently with other methods on this struct. This method only
        /// provides shared access to the inner IO resource when handling the
        /// [`AsyncFdReadyGuard`].
        #[allow(clippy::needless_lifetimes)] // The lifetime improves rustdoc rendering.
        pub async fn readable<'a>(&'a self) -> io::Result<AsyncFdReadyGuard<'a, T>> {
            self.readiness(Interest::READABLE).await
        }

        /// Waits for the file descriptor to become readable, returning a
        /// [`AsyncFdReadyMutGuard`] that must be dropped to resume read-readiness
        /// polling.
        ///
        /// This method takes `&mut self`, so it is possible to access the inner IO
        /// resource mutably when handling the [`AsyncFdReadyMutGuard`].
        #[allow(clippy::needless_lifetimes)] // The lifetime improves rustdoc rendering.
        pub async fn readable_mut<'a>(&'a mut self) -> io::Result<AsyncFdReadyMutGuard<'a, T>> {
            self.readiness_mut(Interest::READABLE).await
        }

        /// Waits for the file descriptor to become writable, returning a
        /// [`AsyncFdReadyGuard`] that must be dropped to resume write-readiness
        /// polling.
        ///
        /// This method takes `&self`, so it is possible to call this method
        /// concurrently with other methods on this struct. This method only
        /// provides shared access to the inner IO resource when handling the
        /// [`AsyncFdReadyGuard`].
        #[allow(clippy::needless_lifetimes)] // The lifetime improves rustdoc rendering.
        pub async fn writable<'a>(&'a self) -> io::Result<AsyncFdReadyGuard<'a, T>> {
            self.readiness(Interest::WRITABLE).await
        }

        /// Waits for the file descriptor to become writable, returning a
        /// [`AsyncFdReadyMutGuard`] that must be dropped to resume write-readiness
        /// polling.
        ///
        /// This method takes `&mut self`, so it is possible to access the inner IO
        /// resource mutably when handling the [`AsyncFdReadyMutGuard`].
        #[allow(clippy::needless_lifetimes)] // The lifetime improves rustdoc rendering.
        pub async fn writable_mut<'a>(&'a mut self) -> io::Result<AsyncFdReadyMutGuard<'a, T>> {
            self.readiness_mut(Interest::WRITABLE).await
        }
    }

    impl<T: AsRawFd> AsRawFd for AsyncFd<T> {
        fn as_raw_fd(&self) -> RawFd {
            self.inner.as_ref().unwrap().as_raw_fd()
        }
    }

    impl<T: std::fmt::Debug + AsRawFd> std::fmt::Debug for AsyncFd<T> {
        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
            f.debug_struct("AsyncFd")
                .field("inner", &self.inner)
                .finish()
        }
    }

    impl<T: AsRawFd> Drop for AsyncFd<T> {
        fn drop(&mut self) {
            let _ = self.take_inner();
        }
    }

    impl<'a, Inner: AsRawFd> AsyncFdReadyGuard<'a, Inner> {
        /// Indicates to tokio that the file descriptor is no longer ready. The
        /// internal readiness flag will be cleared, and tokio will wait for the
        /// next edge-triggered readiness notification from the OS.
        ///
        /// It is critical that this function not be called unless your code
        /// _actually observes_ that the file descriptor is _not_ ready. Do not call
        /// it simply because, for example, a read succeeded; it should be called
        /// when a read is observed to block.
        ///
        /// [`drop`]: method@std::mem::drop
        pub fn clear_ready(&mut self) {
            if let Some(event) = self.event.take() {
                self.async_fd.registration.clear_readiness(event);
            }
        }

        /// This method should be invoked when you intentionally want to keep the
        /// ready flag asserted.
        ///
        /// While this function is itself a no-op, it satisfies the `#[must_use]`
        /// constraint on the [`AsyncFdReadyGuard`] type.
        pub fn retain_ready(&mut self) {
            // no-op
        }

        /// Performs the provided IO operation.
        ///
        /// If `f` returns a [`WouldBlock`] error, the readiness state associated
        /// with this file descriptor is cleared, and the method returns
        /// `Err(TryIoError::WouldBlock)`. You will typically need to poll the
        /// `AsyncFd` again when this happens.
        ///
        /// This method helps ensure that the readiness state of the underlying file
        /// descriptor remains in sync with the tokio-side readiness state, by
        /// clearing the tokio-side state only when a [`WouldBlock`] condition
        /// occurs. It is the responsibility of the caller to ensure that `f`
        /// returns [`WouldBlock`] only if the file descriptor that originated this
        /// `AsyncFdReadyGuard` no longer expresses the readiness state that was queried to
        /// create this `AsyncFdReadyGuard`.
        ///
        /// [`WouldBlock`]: std::io::ErrorKind::WouldBlock
        // Alias for old name in 0.x
        #[cfg_attr(docsrs, doc(alias = "with_io"))]
        pub fn try_io<R>(
            &mut self,
            f: impl FnOnce(&AsyncFd<Inner>) -> io::Result<R>,
        ) -> Result<io::Result<R>, TryIoError> {
            let result = f(self.async_fd);

            if let Err(e) = result.as_ref() {
                if e.kind() == io::ErrorKind::WouldBlock {
                    self.clear_ready();
                }
            }

            match result {
                Err(err) if err.kind() == io::ErrorKind::WouldBlock => Err(TryIoError(())),
                result => Ok(result),
            }
        }
    }

    impl<'a, Inner: AsRawFd> AsyncFdReadyMutGuard<'a, Inner> {
        /// Indicates to tokio that the file descriptor is no longer ready. The
        /// internal readiness flag will be cleared, and tokio will wait for the
        /// next edge-triggered readiness notification from the OS.
        ///
        /// It is critical that this function not be called unless your code
        /// _actually observes_ that the file descriptor is _not_ ready. Do not call
        /// it simply because, for example, a read succeeded; it should be called
        /// when a read is observed to block.
        ///
        /// [`drop`]: method@std::mem::drop
        pub fn clear_ready(&mut self) {
            if let Some(event) = self.event.take() {
                self.async_fd.registration.clear_readiness(event);
            }
        }

        /// This method should be invoked when you intentionally want to keep the
        /// ready flag asserted.
        ///
        /// While this function is itself a no-op, it satisfies the `#[must_use]`
        /// constraint on the [`AsyncFdReadyGuard`] type.
        pub fn retain_ready(&mut self) {
            // no-op
        }

        /// Performs the provided IO operation.
        ///
        /// If `f` returns a [`WouldBlock`] error, the readiness state associated
        /// with this file descriptor is cleared, and the method returns
        /// `Err(TryIoError::WouldBlock)`. You will typically need to poll the
        /// `AsyncFd` again when this happens.
        ///
        /// This method helps ensure that the readiness state of the underlying file
        /// descriptor remains in sync with the tokio-side readiness state, by
        /// clearing the tokio-side state only when a [`WouldBlock`] condition
        /// occurs. It is the responsibility of the caller to ensure that `f`
        /// returns [`WouldBlock`] only if the file descriptor that originated this
        /// `AsyncFdReadyGuard` no longer expresses the readiness state that was queried to
        /// create this `AsyncFdReadyGuard`.
        ///
        /// [`WouldBlock`]: std::io::ErrorKind::WouldBlock
        pub fn try_io<R>(
            &mut self,
            f: impl FnOnce(&mut AsyncFd<Inner>) -> io::Result<R>,
        ) -> Result<io::Result<R>, TryIoError> {
            let result = f(&mut self.async_fd);

            if let Err(e) = result.as_ref() {
                if e.kind() == io::ErrorKind::WouldBlock {
                    self.clear_ready();
                }
            }

            match result {
                Err(err) if err.kind() == io::ErrorKind::WouldBlock => Err(TryIoError(())),
                result => Ok(result),
            }
        }
    }

    impl<'a, T: std::fmt::Debug + AsRawFd> std::fmt::Debug for AsyncFdReadyGuard<'a, T> {
        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
            f.debug_struct("ReadyGuard")
                .field("async_fd", &self.async_fd)
                .finish()
        }
    }

    impl<'a, T: std::fmt::Debug + AsRawFd> std::fmt::Debug for AsyncFdReadyMutGuard<'a, T> {
        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
            f.debug_struct("MutReadyGuard")
                .field("async_fd", &self.async_fd)
                .finish()
        }
    }

    /// The error type returned by [`try_io`].
    ///
    /// This error indicates that the IO resource returned a [`WouldBlock`] error.
    ///
    /// [`WouldBlock`]: std::io::ErrorKind::WouldBlock
    /// [`try_io`]: method@AsyncFdReadyGuard::try_io
    #[derive(Debug)]
    pub struct TryIoError(());