Visitar URL original
io: add get_{ref,mut} methods to AsyncFdReadyGuard and AsyncFdReadyMutGuard. by brain0 · Pull Request #3807 · tokio-rs/tokio · GitHub
Skip to content

io: add get_{ref,mut} methods to AsyncFdReadyGuard and AsyncFdReadyMutGuard. - #3807

Merged
Darksonn merged 3 commits into
tokio-rs:masterfrom
brain0:asyncfd_get_mut
Jun 16, 2021
Merged

Darksonn merged 3 commits into
tokio-rs:masterfrom
brain0:asyncfd_get_mut

Conversation

@brain0

@brain0 brain0 commented May 22, 2021

Copy link
Copy Markdown
Contributor

The only way to use AsyncFdReadyMutGuard currently is through try_io, since it is impossible to access the underlying object. In some situations, it is desirable to use clear_ready and retain_ready directly instead of try_io. Enable this by adding get_ref and get_mut methods.

Motivation

When using AsyncFd with an I/O object that does not communicate readiness through ErrorKind::WouldBlock, code using try_io becomes hard to read. In the following example, the next() method returns None when no new data is ready.

let mut guard = ready!(self.inner.poll_read_ready_mut(cx))?;

match guard.try_io(|s| {
    s.get_mut()
        .next()
        .ok_or_else(|| ErrorKind::WouldBlock.into())
}) {
    Ok(event) => Poll::Ready(Some(event)),
    Err(_) => Poll::Pending,
}

As seen here, you have to explicitly convert None to a WouldBlock error in try_io, only to convert that error back into Pending afterwards. This is confusing to read.

Solution

By adding AsyncFdReadyMutGuard::get_mut, this can be expressed in a more straight-forward way:

let mut guard = ready!(self.inner.poll_read_ready_mut(cx))?;

match guard.get_mut().get_mut().next() {
    Some(event) => {
        guard.retain_ready();
        Poll::Ready(Some(Ok(event)))
    }
    None => {
        guard.clear_ready();
        Poll::Pending
    }
}

The get_ref methods are added for consistency.

Questions

Should we return a reference to AsyncFd<T> or T? try_io uses AsyncFd<T> in its argument, so the proposed solution is consistent. On the other hand, in probably all cases, this requires writing guard.get_mut().get_mut().

…tGuard.

The only way to use AsyncFdReadyMutGuard currently is through try_io,
since it is impossible to access the underlying object. In some
situations, it is desirable to use clear_ready and retain_ready directly
instead of try_io. Enable this by adding get_ref and get_mut methods.
@Darksonn Darksonn added A-tokio Area: The main tokio crate M-io Module: tokio/io labels May 23, 2021
@Darksonn

Copy link
Copy Markdown
Member

One option is to also add an get_inner_mut method?

@brain0

brain0 commented May 26, 2021

Copy link
Copy Markdown
Contributor Author

Yes. So, would you rather see four methods get_ref, get_mut, get_inner_ref and get_inner_mut, or only the latter two?

I personally doubt that accessing the AsyncFd<T> is useful in any way, I was confused when I saw that the closure passed to try_io takes AsyncFd<T> instead of T.

@Darksonn

Copy link
Copy Markdown
Member

We can add all four. Even if it isn't very useful right now, it might get new methods in the future where it is useful.

Comment thread tokio/src/io/async_fd.rs Outdated
Comment on lines +483 to +491
/// Returns a shared reference to the inner [`AsyncFd`].
pub fn get_ref(&self) -> &AsyncFd<Inner> {
self.async_fd
}

/// Returns a shared reference to the backing object of the inner [`AsyncFd`].
pub fn get_inner(&self) -> &Inner {
self.get_ref().get_ref()
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you move the methods to the bottom of the impl block so they don't appear at the top of the documentation?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-tokio Area: The main tokio crate M-io Module: tokio/io

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants