Spec-Zone.ru › Tokio

Структура AsyncFd

pub struct AsyncFd<T: AsRawFd> { /* private fields */ }
Доступно только в Unix и при включённой возможности ящика net.

Связывает объект ввода-вывода, основанный на файловом дескрипторе Unix, с реактором tokio, позволяя проверять готовность. Файловый дескриптор должен относиться к типу, который можно использовать со средствами опроса ОС (то есть poll, epoll, kqueue и т. д.), например сетевому сокету или каналу, и для файлового дескриптора должен быть установлен неблокирующий режим.

Создание AsyncFd регистрирует файловый дескриптор в текущем реакторе tokio, позволяя напрямую ожидать, пока файловый дескриптор станет доступен для чтения или записи. После регистрации файловый дескриптор остаётся зарегистрированным, пока AsyncFd не будет уничтожен.

AsyncFd принимает во владение произвольный объект, представляющий объект ввода-вывода. Предполагается, что внутренний объект закроет файловый дескриптор при уничтожении, предотвращая утечки ресурсов и гарантируя, что AsyncFd сможет очистить регистрацию до закрытия файлового дескриптора. Функцию AsyncFd::into_inner можно использовать, чтобы извлечь внутренний объект и вернуть управление из реактора ввода-вывода tokio. Тип OwnedFd часто используется в качестве внутреннего объекта, поскольку это самый простой тип, закрывающий fd при уничтожении.

Внутренний объект должен реализовывать AsRawFd. Этот файловый дескриптор не должен изменяться, пока AsyncFd владеет внутренним объектом, то есть метод AsRawFd::as_raw_fd внутреннего типа при каждом вызове должен возвращать один и тот же файловый дескриптор. Несоблюдение этого требования приводит к неопределённому поведению драйвера ввода-вывода, в том числе может нарушить уведомления для других сокетов и т. п.

Проверка готовности выполняется вызовом асинхронных функций readable и writable. Эти функции завершаются, когда обнаруживается соответствующее условие готовности. Любое количество задач может параллельно проверять один и тот же AsyncFd, как по одному и тому же условию, так и по разным.

На некоторых платформах механизм обнаружения готовности использует уведомления, срабатывающие по фронту. Это означает, что ОС уведомит Tokio только при переходе файлового дескриптора из состояния неготовности в состояние готовности. Для корректной работы сначала следует попытаться выполнить чтение или запись и проверять готовность только в случае ошибки std::io::ErrorKind::WouldBlock.

Tokio внутренне отслеживает получение уведомления о готовности. Когда вызываются функции проверки готовности, такие как readable и writable, эти асинхронные функции завершаются немедленно, если установлен флаг готовности. Однако это означает, что крайне важно сбрасывать этот флаг тогда и только тогда, когда файловый дескриптор перестаёт быть готовым. Возвращаемый функциями проверки готовности объект AsyncFdReadyGuard выполняет эту задачу; после вызова асинхронной функции проверки готовности необходимо использовать этот AsyncFdReadyGuard, чтобы сообщить tokio, перестал ли файловый дескриптор быть готовым.

Использование с API на основе опроса

В некоторых случаях может быть желательно использовать AsyncFd с API, подобными TcpStream::poll_read_ready. Для этого предусмотрены функции AsyncFd::poll_read_ready и AsyncFd::poll_write_ready. Поскольку эти функции не создают future для хранения своего состояния, у них есть ограничение: в каждый момент времени на каждом направлении (чтение или запись) может ожидать только одна задача.

Примеры

В этом примере показано, как сделать std::net::TcpStream асинхронным с помощью AsyncFd. Операции чтения и записи реализованы как async fn, а также с использованием трейтов ввода-вывода AsyncRead и AsyncWrite.

use std::io::{self, Read, Write};
use std::net::TcpStream;
use std::pin::Pin;
use std::task::{ready, Context, Poll};
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
use tokio::io::unix::AsyncFd;

pub struct AsyncTcpStream {
    inner: AsyncFd<TcpStream>,
}

impl AsyncTcpStream {
    pub fn new(tcp: TcpStream) -> io::Result<Self> {
        tcp.set_nonblocking(true)?;
        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,
            }
        }
    }

    pub async fn write(&self, buf: &[u8]) -> io::Result<usize> {
        loop {
            let mut guard = self.inner.writable().await?;

            match guard.try_io(|inner| inner.get_ref().write(buf)) {
                Ok(result) => return result,
                Err(_would_block) => continue,
            }
        }
    }
}

impl AsyncRead for AsyncTcpStream {
    fn poll_read(
        self: Pin<&mut Self>,
        cx: &mut Context<'_>,
        buf: &mut ReadBuf<'_>
    ) -> Poll<io::Result<()>> {
        loop {
            let mut guard = ready!(self.inner.poll_read_ready(cx))?;

            let unfilled = buf.initialize_unfilled();
            match guard.try_io(|inner| inner.get_ref().read(unfilled)) {
                Ok(Ok(len)) => {
                    buf.advance(len);
                    return Poll::Ready(Ok(()));
                },
                Ok(Err(err)) => return Poll::Ready(Err(err)),
                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(()))
    }
}

Реализации

impl<T: AsRawFd> AsyncFd<T>

pub fn new(inner: T) -> Result<Self>
where T: AsRawFd,

Создаёт AsyncFd, использующий объект, реализующий AsRawFd, и принимающий его во владение. Файловый дескриптор используемого объекта кэшируется при создании.

Настраивает только интересы Interest::READABLE и Interest::WRITABLE. Для более точной настройки используйте AsyncFd::with_interest.

Этот метод необходимо вызывать в контексте среды выполнения tokio.

Паника

Эта функция вызывает панику, если текущий реактор не установлен или если флаг функции rt не включён.

pub fn with_interest(inner: T, interest: Interest) -> Result<Self>
where T: AsRawFd,

Создаёт AsyncFd с указанным Interest, использующий объект, реализующий AsRawFd, и принимающий его во владение. Файловый дескриптор используемого объекта кэшируется при создании.

Паника

Эта функция вызывает панику, если текущий реактор не установлен или если флаг функции rt не включён.

pub fn try_new(inner: T) -> Result<Self, AsyncFdTryNewError<T>>
where T: AsRawFd,

Создаёт AsyncFd, использующий объект, реализующий AsRawFd, и принимающий его во владение. Файловый дескриптор используемого объекта кэшируется при создании.

Настраивает только интересы Interest::READABLE и Interest::WRITABLE. Для более точной настройки используйте AsyncFd::try_with_interest.

Этот метод необходимо вызывать в контексте среды выполнения tokio.

В случае ошибки возвращает AsyncFdTryNewError, содержащую исходный объект, переданный этой функции.

Паника

Эта функция вызывает панику, если текущий реактор не установлен или если флаг функции rt не включён.

pub fn try_with_interest( inner: T, interest: Interest, ) -> Result<Self, AsyncFdTryNewError<T>>
where T: AsRawFd,

Создаёт AsyncFd с указанным Interest, использующий объект, реализующий AsRawFd, и принимающий его во владение. Файловый дескриптор используемого объекта кэшируется при создании.

В случае ошибки возвращает AsyncFdTryNewError, содержащую исходный объект, переданный этой функции.

Паника

Эта функция вызывает панику, если текущий реактор не установлен или если флаг функции rt не включён.

pub fn get_ref(&self) -> &T

Возвращает общую ссылку на используемый объект этого AsyncFd.

pub fn get_mut(&mut self) -> &mut T

Возвращает изменяемую ссылку на используемый объект этого AsyncFd.

pub fn into_inner(self) -> T

Отменяет регистрацию этого файлового дескриптора и возвращает владение базовым объектом.

pub fn poll_read_ready<'a>( &'a self, cx: &mut Context<'_>, ) -> Poll<Result<AsyncFdReadyGuard<'a, T>>>

Ожидает готовности к чтению.

Если файловый дескриптор в данный момент не готов к чтению, этот метод сохранит копию Waker из переданного Context. Когда файловый дескриптор будет готов к чтению, будет вызван Waker::wake.

Обратите внимание: при нескольких вызовах poll_read_ready или poll_read_ready_mut пробуждение будет запланировано только для Waker из Context, переданного в последнем вызове. (При этом poll_write_ready сохраняет второй независимый waker).

Этот метод предназначен для случаев, когда невозможно создать и закрепить future с помощью readable. Если возможно, предпочтительно использовать readable, поскольку это позволяет нескольким задачам одновременно выполнять опрос.

Этот метод принимает &self, поэтому его можно вызывать параллельно с другими методами этой структуры. Этот метод предоставляет общий доступ к внутреннему ресурсу ввода-вывода только при работе с AsyncFdReadyGuard.

pub fn poll_read_ready_mut<'a>( &'a mut self, cx: &mut Context<'_>, ) -> Poll<Result<AsyncFdReadyMutGuard<'a, T>>>

Ожидает готовности к чтению.

Если файловый дескриптор в данный момент не готов к чтению, этот метод сохранит копию Waker из переданного Context. Когда файловый дескриптор будет готов к чтению, будет вызван Waker::wake.

Обратите внимание: при нескольких вызовах poll_read_ready или poll_read_ready_mut пробуждение будет запланировано только для Waker из Context, переданного в последнем вызове. (При этом poll_write_ready сохраняет второй независимый waker).

Этот метод предназначен для случаев, когда невозможно создать и закрепить future с помощью readable. Если возможно, предпочтительно использовать readable, поскольку это позволяет нескольким задачам одновременно выполнять опрос.

Этот метод принимает &mut self, поэтому при работе с AsyncFdReadyMutGuard можно изменять внутренний ресурс ввода-вывода.

pub fn poll_write_ready<'a>( &'a self, cx: &mut Context<'_>, ) -> Poll<Result<AsyncFdReadyGuard<'a, T>>>

Проверяет готовность к записи.

Если файловый дескриптор в данный момент не готов к записи, этот метод сохранит копию Waker из переданного Context. Когда файловый дескриптор будет готов к записи, будет вызван Waker::wake.

Обратите внимание: при нескольких вызовах poll_write_ready или poll_write_ready_mut пробуждение запланировано только для Waker из Context, переданного при последнем вызове. (При этом poll_read_ready сохраняет второй, независимый waker).

Этот метод предназначен для случаев, когда невозможно создать и закрепить future с помощью writable. Если возможно, предпочтительнее использовать writable, поскольку этот вариант позволяет одновременно выполнять опрос из нескольких задач.

Этот метод принимает &self, поэтому его можно вызывать одновременно с другими методами этой структуры. При обработке AsyncFdReadyGuard этот метод предоставляет только совместный доступ к внутреннему ресурсу ввода-вывода.

pub fn poll_write_ready_mut<'a>( &'a mut self, cx: &mut Context<'_>, ) -> Poll<Result<AsyncFdReadyMutGuard<'a, T>>>

Проверяет готовность к записи.

Если файловый дескриптор в данный момент не готов к записи, этот метод сохранит копию Waker из переданного Context. Когда файловый дескриптор будет готов к записи, будет вызван Waker::wake.

Обратите внимание: при нескольких вызовах poll_write_ready или poll_write_ready_mut пробуждение запланировано только для Waker из Context, переданного при последнем вызове. (При этом poll_read_ready сохраняет второй, независимый waker).

Этот метод предназначен для случаев, когда невозможно создать и закрепить future с помощью writable. Если возможно, предпочтительнее использовать writable, поскольку этот вариант позволяет одновременно выполнять опрос из нескольких задач.

Этот метод принимает &mut self, поэтому при обработке AsyncFdReadyMutGuard можно получить изменяемый доступ к внутреннему ресурсу ввода-вывода.

pub async fn ready( &self, interest: Interest, ) -> Result<AsyncFdReadyGuard<'_, T>>

Ожидает наступления любого из запрошенных состояний готовности и возвращает AsyncFdReadyGuard, который необходимо уничтожить, чтобы возобновить опрос запрошенных состояний готовности.

Функция может завершиться, даже если файловый дескриптор не готов. Это ложноположительный результат, и попытка выполнить операцию завершится с io::ErrorKind::WouldBlock. Функция также может вернуть пустой набор Ready, поэтому всегда проверяйте возвращённое значение и, возможно, ожидайте снова, если запрошенные состояния не установлены.

Если операция ввода-вывода завершается с io::ErrorKind::WouldBlock, состояние готовности необходимо сбросить. При использовании объединённого интереса важно сбрасывать только то состояние готовности, которое фактически помешало выполнению операции. Например, если используется объединённый интерес Interest::READABLE | Interest::WRITABLE и операция чтения блокируется, следует сбросить только готовность к чтению с помощью метода AsyncFdReadyGuard::clear_ready_matching: guard.clear_ready_matching(Ready::READABLE). Сбрасывать готовность к записи в этом случае также было бы неправильно. Метод AsyncFdReadyGuard::clear_ready сбрасывает все флаги готовности.

Этот метод принимает &self, поэтому его можно вызывать одновременно с другими методами этой структуры. Этот метод предоставляет совместный доступ к внутреннему ресурсу ввода-вывода при работе с AsyncFdReadyGuard.

Примеры

Одновременное чтение и запись в std::net::TcpStream в рамках одной задачи без разделения.

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 async fn ready_mut( &mut self, interest: Interest, ) -> Result<AsyncFdReadyMutGuard<'_, T>>

Ожидает наступления любого из запрошенных состояний готовности и возвращает AsyncFdReadyMutGuard, который необходимо уничтожить, чтобы возобновить опрос запрошенных состояний готовности.

Функция может завершиться, даже если файловый дескриптор не готов. Это ложноположительный результат, и попытка выполнить операцию завершится с io::ErrorKind::WouldBlock. Функция также может вернуть пустой набор Ready, поэтому всегда проверяйте возвращённое значение и, возможно, ожидайте снова, если запрошенные состояния не установлены.

Если операция ввода-вывода завершается с io::ErrorKind::WouldBlock, состояние готовности необходимо сбросить. При использовании объединённого интереса важно сбрасывать только то состояние готовности, которое фактически помешало выполнению операции. Например, если используется объединённый интерес Interest::READABLE | Interest::WRITABLE и операция чтения блокируется, следует сбросить только готовность к чтению с помощью метода AsyncFdReadyMutGuard::clear_ready_matching: guard.clear_ready_matching(Ready::READABLE). Сбрасывать готовность к записи в этом случае также было бы неправильно. Метод AsyncFdReadyMutGuard::clear_ready сбрасывает все флаги готовности.

Этот метод принимает &mut self, поэтому при работе с AsyncFdReadyMutGuard можно получить изменяемый доступ к внутреннему ресурсу ввода-вывода.

Примеры

Одновременное чтение и запись в std::net::TcpStream в рамках одной задачи без разделения.

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 mut stream = AsyncFd::new(stream)?;

    loop {
        let mut guard = stream
            .ready_mut(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 guard.get_inner_mut().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 guard.get_inner_mut().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 async fn readable<'a>(&'a self) -> Result<AsyncFdReadyGuard<'a, T>>

Ожидает, пока файловый дескриптор станет доступен для чтения, и возвращает AsyncFdReadyGuard, который необходимо уничтожить, чтобы возобновить опрос готовности к чтению.

Этот метод принимает &self, поэтому его можно вызывать одновременно с другими методами этой структуры. Этот метод предоставляет совместный доступ к внутреннему ресурсу ввода-вывода при работе с AsyncFdReadyGuard.

Безопасность отмены

Этот метод безопасен при отмене. После наступления события готовности метод будет сразу возвращать результат, пока это событие не будет обработано попыткой чтения или записи, завершившейся с WouldBlock или Poll::Pending.

pub async fn readable_mut<'a>( &'a mut self, ) -> Result<AsyncFdReadyMutGuard<'a, T>>

Ожидает, пока файловый дескриптор станет доступен для чтения, и возвращает AsyncFdReadyMutGuard, который необходимо удалить, чтобы возобновить проверку готовности к чтению.

Этот метод принимает &mut self, поэтому при обработке AsyncFdReadyMutGuard можно получить изменяемый доступ к внутреннему ресурсу ввода-вывода.

Безопасность при отмене

Этот метод безопасен при отмене. После возникновения события готовности метод будет немедленно возвращать результат, пока событие готовности не будет обработано попыткой чтения или записи, завершившейся ошибкой WouldBlock или Poll::Pending.

pub async fn writable<'a>(&'a self) -> Result<AsyncFdReadyGuard<'a, T>>

Ожидает, пока файловый дескриптор станет доступен для записи, и возвращает AsyncFdReadyGuard, который необходимо удалить, чтобы возобновить проверку готовности к записи.

Этот метод принимает &self, поэтому его можно вызывать одновременно с другими методами этой структуры. При обработке AsyncFdReadyGuard этот метод предоставляет только совместный доступ к внутреннему ресурсу ввода-вывода.

Безопасность при отмене

Этот метод безопасен при отмене. После возникновения события готовности метод будет немедленно возвращать результат, пока событие готовности не будет обработано попыткой чтения или записи, завершившейся ошибкой WouldBlock или Poll::Pending.

pub async fn writable_mut<'a>( &'a mut self, ) -> Result<AsyncFdReadyMutGuard<'a, T>>

Ожидает, пока файловый дескриптор станет доступен для записи, и возвращает AsyncFdReadyMutGuard, который необходимо удалить, чтобы возобновить проверку готовности к записи.

Этот метод принимает &mut self, поэтому при обработке AsyncFdReadyMutGuard можно получить изменяемый доступ к внутреннему ресурсу ввода-вывода.

Безопасность при отмене

Этот метод безопасен при отмене. После возникновения события готовности метод будет немедленно возвращать результат, пока событие готовности не будет обработано попыткой чтения или записи, завершившейся ошибкой WouldBlock или Poll::Pending.

pub async fn async_io<R>( &self, interest: Interest, f: impl FnMut(&T) -> Result<R>, ) -> Result<R>

Читает данные из файлового дескриптора или записывает их в него с помощью предоставленной пользователем операции ввода-вывода.

Метод async_io — это вспомогательный метод, который ожидает готовности файлового дескриптора, а затем выполняет предоставленную операцию ввода-вывода. Поскольку файловые дескрипторы могут ошибочно считаться готовыми, замыкание будет вызываться повторно, пока оно не вернёт значение, отличное от ошибки WouldBlock. Это выполняется с помощью следующего цикла:

async fn async_io<R>(&self, mut f: impl FnMut(&T) -> io::Result<R>) -> io::Result<R> {
    loop {
        // or `readable` if called with the read interest.
        let guard = self.writable().await?;

        match guard.try_io(&mut f) {
            Ok(result) => return result,
            Err(_would_block) => continue,
        }
    }
}

Замыкание должно возвращать ошибку WouldBlock только в том случае, если оно выполнило операцию ввода-вывода с файловым дескриптором, которая завершилась неудачей из-за его неготовности. Возврат ошибки WouldBlock в любой другой ситуации приведёт к некорректному сбросу флага готовности, из-за чего файловый дескриптор может работать неправильно.

Замыкание не должно выполнять операцию ввода-вывода с помощью методов типа Tokio AsyncFd, поскольку это нарушит работу флага готовности и может привести к неправильной работе файлового дескриптора.

Этот метод не предназначен для использования с комбинированными интересами. Замыкание должно выполнять только один тип операции ввода-вывода, поэтому ему не должно требоваться более одного состояния готовности. Вызов этого метода с комбинированным интересом может привести к панике или бесконечному ожиданию.

Примеры

В этом примере отправляются байты через внутренний объект std::net::UdpSocket. Метод async_io ожидает готовности и повторяет попытку, если операция отправки блокируется. Этот пример эквивалентен примеру для try_io.

use tokio::io::{Interest, 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 = async_fd
        .async_io(Interest::WRITABLE, |inner| inner.send(&[1, 2]))
        .await?;

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

    Ok(())
}

pub async fn async_io_mut<R>( &mut self, interest: Interest, f: impl FnMut(&mut T) -> Result<R>, ) -> Result<R>

Читает данные из файлового дескриптора или записывает их в него с помощью предоставленной пользователем операции ввода-вывода.

Поведение такое же, как у async_io, за исключением того, что замыкание может изменять внутреннее значение AsyncFd.

pub fn try_io<R>( &self, interest: Interest, f: impl FnOnce(&T) -> Result<R>, ) -> Result<R>

Пытается прочитать данные из файлового дескриптора или записать их в него с помощью предоставленной пользователем операции ввода-вывода.

Если файловый дескриптор готов, вызывается предоставленное замыкание. Замыкание должно попытаться выполнить операцию ввода-вывода над файловым дескриптором, вручную вызвав соответствующий системный вызов. Если операция завершается неудачей, потому что файловый дескриптор фактически не готов, замыкание должно вернуть ошибку WouldBlock, после чего флаг готовности сбрасывается. Затем возвращается значение, возвращённое замыканием, — try_io.

Если файловый дескриптор не готов, замыкание не вызывается и возвращается ошибка WouldBlock.

Замыкание должно возвращать ошибку WouldBlock только в том случае, если оно выполнило операцию ввода-вывода над файловым дескриптором, которая завершилась неудачей из-за того, что файловый дескриптор не был готов. Возврат ошибки WouldBlock в любой другой ситуации приведёт к некорректному сбросу флага готовности, что может вызвать неправильную работу файлового дескриптора.

Замыкание не должно выполнять операцию ввода-вывода с помощью методов, определённых для типа Tokio AsyncFd, поскольку это нарушит работу флага готовности и может вызвать неправильную работу файлового дескриптора.

Этот метод не предназначен для использования с объединёнными интересами. Замыкание должно выполнять только один тип операции ввода-вывода, поэтому ему не должно требоваться более одного состояния готовности. Этот метод может вызвать панику или навсегда приостановить выполнение, если его вызвать с объединённым интересом.

pub fn try_io_mut<R>( &mut self, interest: Interest, f: impl FnOnce(&mut T) -> Result<R>, ) -> Result<R>

Пытается прочитать данные из файлового дескриптора или записать их в него с помощью предоставленной пользователем операции ввода-вывода.

Поведение такое же, как у try_io, за исключением того, что замыкание может изменять внутреннее значение AsyncFd.

Реализации трейтов

impl<T: AsRawFd> AsFd for AsyncFd<T>

fn as_fd(&self) -> BorrowedFd<'_>

Заимствует файловый дескриптор. Подробнее

impl<T: AsRawFd> AsRawFd for AsyncFd<T>

fn as_raw_fd(&self) -> RawFd

Извлекает необработанный файловый дескриптор. Подробнее

impl<T: Debug + AsRawFd> Debug for AsyncFd<T>

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

Форматирует значение с помощью указанного форматировщика. Подробнее

impl<T: AsRawFd> Drop for AsyncFd<T>

fn drop(&mut self)

Выполняет деструктор для этого типа. Подробнее

fn pin_drop(self: Pin<&mut Self>)

🔬Это экспериментальный API, доступный только в nightly. (pin_ergonomics)
Выполняет деструктор для этого типа, но, в отличие от Drop::drop, требует, чтобы self был закреплён. Подробнее

Реализации автоматических трейтов

impl<T> !RefUnwindSafe for AsyncFd<T>

impl<T> !UnwindSafe for AsyncFd<T>

impl<T> Freeze for AsyncFd<T>
where T: Freeze,

impl<T> Send for AsyncFd<T>
where T: Send,

impl<T> Sync for AsyncFd<T>
where T: Sync,

impl<T> Unpin for AsyncFd<T>
where T: Unpin,

impl<T> UnsafeUnpin for AsyncFd<T>
where T: UnsafeUnpin,

Общие реализации

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

fn type_id(&self) -> TypeId

Получает TypeId для self. Подробнее

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

fn borrow(&self) -> &T

Неизменяемо заимствует из принадлежащего значения. Подробнее

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

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

Изменяемо заимствует из принадлежащего значения. Подробнее

impl<T> From<T> for T

fn from(t: T) -> T

Возвращает аргумент без изменений.

impl<T> Instrument for T

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

Инструментирует этот тип с помощью указанного Span, возвращая обёртку Instrumented. Подробнее

fn in_current_span(self) -> Instrumented<Self> ⓘ

Инструментирует этот тип с помощью текущего Span, возвращая обёртку Instrumented. Подробнее

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

fn into(self) -> U

Вызывает U::from(self).

То есть это преобразование выполняется так, как предписывает реализация From<T> for U.

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

type Error = Infallible

Тип, возвращаемый в случае ошибки преобразования.

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

Выполняет преобразование.

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

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

Тип, возвращаемый в случае ошибки преобразования.

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

Выполняет преобразование.

impl<T> WithSubscriber for T

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

Присоединяет указанный Subscriber к этому типу и возвращает обёртку WithDispatch. Подробнее

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Присоединяет текущий по умолчанию Subscriber к этому типу и возвращает обёртку WithDispatch. Подробнее

MIT License
Copyright © Tokio Contributors
https://docs.rs/tokio/1.53.1/tokio/io/unix/struct.AsyncFd.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API