AsyncFdReadyGuard

Struct AsyncFdReadyGuard 

pub struct AsyncFdReadyGuard<'a, T>
where T: AsRawFd,
{ async_fd: &'a AsyncFd<T>, event: Option<ReadyEvent>, }
Expand description

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.

Fields§

§async_fd: &'a AsyncFd<T>§event: Option<ReadyEvent>

Implementations§

§

impl<'a, Inner> AsyncFdReadyGuard<'a, Inner>
where Inner: AsRawFd,

pub fn clear_ready(&mut self)

Indicates to tokio that the file descriptor is no longer ready. All internal readiness flags will be cleared, and tokio will wait for the next edge-triggered readiness notification from the OS.

This function is commonly used with guards returned by AsyncFd::readable and AsyncFd::writable.

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.

This method only clears readiness events that happened before the creation of this guard. In other words, if the IO resource becomes ready between the creation of the guard and this call to clear_ready, then the readiness is not actually cleared.

pub fn clear_ready_matching(&mut self, ready: Ready)

Indicates to tokio that the file descriptor no longer has a specific readiness. The internal readiness flag will be cleared, and tokio will wait for the next edge-triggered readiness notification from the OS.

This function is useful in combination with the AsyncFd::ready method when a combined interest like Interest::READABLE | Interest::WRITABLE is used.

It is critical that this function not be called unless your code actually observes that the file descriptor is not ready for the provided Ready. Do not call it simply because, for example, a read succeeded; it should be called when a read is observed to block. Only clear the specific readiness that is observed to block. For example when a read blocks when using a combined interest, only clear Ready::READABLE.

This method only clears readiness events that happened before the creation of this guard. In other words, if the IO resource becomes ready between the creation of the guard and this call to clear_ready_matching, then the readiness is not actually cleared.

§Examples

Concurrently read and write to a std::net::TcpStream on the same task without splitting.

use std::error::Error;
use std::io;
use std::io::{Read, Write};
use std::net::TcpStream;
use tokio::io::unix::AsyncFd;
use tokio::io::{Interest, Ready};

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    let stream = TcpStream::connect("127.0.0.1:8080")?;
    stream.set_nonblocking(true)?;
    let stream = AsyncFd::new(stream)?;

    loop {
        let mut guard = stream
            .ready(Interest::READABLE | Interest::WRITABLE)
            .await?;

        if guard.ready().is_readable() {
            let mut data = vec![0; 1024];
            // Try to read data, this may still fail with `WouldBlock`
            // if the readiness event is a false positive.
            match stream.get_ref().read(&mut data) {
                Ok(n) => {
                    println!("read {} bytes", n);
                }
                Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
                    // a read has blocked, but a write might still succeed.
                    // clear only the read readiness.
                    guard.clear_ready_matching(Ready::READABLE);
                    continue;
                }
                Err(e) => {
                    return Err(e.into());
                }
            }
        }

        if guard.ready().is_writable() {
            // Try to write data, this may still fail with `WouldBlock`
            // if the readiness event is a false positive.
            match stream.get_ref().write(b"hello world") {
                Ok(n) => {
                    println!("write {} bytes", n);
                }
                Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
                    // a write has blocked, but a read might still succeed.
                    // clear only the write readiness.
                    guard.clear_ready_matching(Ready::WRITABLE);
                    continue;
                }
                Err(e) => {
                    return Err(e.into());
                }
            }
        }
    }
}

pub fn retain_ready(&mut self)

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 ready(&self) -> Ready

Get the Ready value associated with this guard.

This method will return the empty readiness state if AsyncFdReadyGuard::clear_ready has been called on the guard.

pub fn try_io<R>( &mut self, f: impl FnOnce(&'a AsyncFd<Inner>) -> Result<R, Error>, ) -> Result<Result<R, Error>, TryIoError>

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.

§Examples

This example sends some bytes to the inner std::net::UdpSocket. Waiting for write-readiness and retrying when the send operation does block are explicit. This example can be written more succinctly using AsyncFd::async_io.

use tokio::io::unix::AsyncFd;

use std::io;
use std::net::UdpSocket;

#[tokio::main]
async fn main() -> io::Result<()> {
    let socket = UdpSocket::bind("0.0.0.0:8080")?;
    socket.set_nonblocking(true)?;
    let async_fd = AsyncFd::new(socket)?;

    let written = loop {
        let mut guard = async_fd.writable().await?;
        match guard.try_io(|inner| inner.get_ref().send(&[1, 2])) {
            Ok(result) => {
                break result?;
            }
            Err(_would_block) => {
                // try_io already cleared the file descriptor's readiness state
                continue;
            }
        }
    };

    println!("wrote {written} bytes");

    Ok(())
}

pub fn get_ref(&self) -> &'a AsyncFd<Inner>

Returns a shared reference to the inner AsyncFd.

pub fn get_inner(&self) -> &'a Inner

Returns a shared reference to the backing object of the inner AsyncFd.

Trait Implementations§

§

impl<'a, T> Debug for AsyncFdReadyGuard<'a, T>
where T: Debug + AsRawFd,

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<'a, T> Freeze for AsyncFdReadyGuard<'a, T>

§

impl<'a, T> !RefUnwindSafe for AsyncFdReadyGuard<'a, T>

§

impl<'a, T> Send for AsyncFdReadyGuard<'a, T>
where T: Sync,

§

impl<'a, T> Sync for AsyncFdReadyGuard<'a, T>
where T: Sync,

§

impl<'a, T> Unpin for AsyncFdReadyGuard<'a, T>

§

impl<'a, T> !UnwindSafe for AsyncFdReadyGuard<'a, T>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T> Chain<T> for T

§

fn len(&self) -> usize

The number of items that this chain link consists of.
§

fn append_to(self, v: &mut Vec<T>)

Append the elements in this link to the chain.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
§

impl<T> Pointable for T

§

const ALIGN: usize

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
§

impl<T> PolicyExt for T
where T: ?Sized,

§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] only if self and other return Action::Follow. Read more
§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
§

impl<T> ServiceExt for T

§

fn map_response_body<F>(self, f: F) -> MapResponseBody<Self, F>
where Self: Sized,

Apply a transformation to the response body. Read more
§

fn decompression(self) -> Decompression<Self>
where Self: Sized,

Decompress response bodies. Read more
§

fn trace_for_http(self) -> Trace<Self, SharedClassifier<ServerErrorsAsFailures>>
where Self: Sized,

High level tracing that classifies responses using HTTP status codes. Read more
§

fn trace_for_grpc(self) -> Trace<Self, SharedClassifier<GrpcErrorsAsFailures>>
where Self: Sized,

High level tracing that classifies responses using gRPC headers. Read more
§

fn follow_redirects(self) -> FollowRedirect<Self>
where Self: Sized,

Follow redirect resposes using the Standard policy. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

impl<T> ErasedDestructor for T
where T: 'static,