Структура Async FdReady Guard
pub struct AsyncFdReadyGuard<'a, T: AsRawFd> { /* private fields */ }
net.Представляет событие готовности ввода-вывода, обнаруженное для определённого файлового дескриптора и ещё не подтверждённое. Это структура must_use, которая помогает убедиться, что вы не забудете явно сбросить событие (или оставить его без сброса).
Этот тип предоставляет неизменяемую ссылку на базовый объект ввода-вывода.
Реализации
impl<'a, Inner: AsRawFd> AsyncFdReadyGuard<'a, Inner>
pub fn clear_ready(&mut self)
Сообщает tokio, что файловый дескриптор больше не готов к выполнению операции. Все внутренние флаги готовности будут сброшены, и tokio будет ожидать следующего уведомления ОС о готовности, инициируемого фронтом.
Эта функция обычно используется с защитниками, возвращаемыми методами AsyncFd::readable и AsyncFd::writable.
Крайне важно не вызывать эту функцию, если ваш код действительно не обнаружил, что файловый дескриптор не готов. Не вызывайте её лишь потому, что, например, чтение завершилось успешно; её следует вызывать, когда обнаружено, что чтение блокируется.
Этот метод сбрасывает только события готовности, произошедшие до создания этого защитника. Иными словами, если ресурс ввода-вывода становится готовым между созданием защитника и этим вызовом clear_ready, готовность фактически не сбрасывается.
pub fn clear_ready_matching(&mut self, ready: Ready)
Сообщает tokio, что файловый дескриптор больше не имеет определённого состояния готовности. Внутренний флаг готовности будет сброшен, и tokio будет ожидать следующего уведомления ОС о готовности, инициируемого фронтом.
Эта функция полезна в сочетании с методом AsyncFd::ready, когда используется объединённый интерес, например Interest::READABLE | Interest::WRITABLE.
Крайне важно не вызывать эту функцию, если ваш код действительно не обнаружил, что файловый дескриптор не готов для указанного значения Ready. Не вызывайте её лишь потому, что, например, чтение завершилось успешно; её следует вызывать, когда обнаружено, что чтение блокируется. Сбрасывайте только то состояние готовности, которое, как обнаружено, блокирует выполнение. Например, если при чтении возникает блокировка при использовании объединённого интереса, сбрасывайте только Ready::READABLE.
Этот метод сбрасывает только события готовности, произошедшие до создания этого защитника. Иными словами, если ресурс ввода-вывода становится готовым между созданием защитника и этим вызовом clear_ready_matching, готовность фактически не сбрасывается.
Примеры
Чтение и запись в 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 fn retain_ready(&mut self)
Этот метод следует вызывать, если вы намеренно хотите оставить флаг готовности установленным.
Хотя сама эта функция ничего не делает, она удовлетворяет требованию #[must_use] для типа AsyncFdReadyGuard.
pub fn ready(&self) -> Ready
Получает значение Ready, связанное с этим защитником.
Этот метод возвращает пустое состояние готовности, если для защитника был вызван метод AsyncFdReadyGuard::clear_ready.
pub fn try_io<R>( &mut self, f: impl FnOnce(&'a AsyncFd<Inner>) -> Result<R>, ) -> Result<Result<R>, TryIoError>
Выполняет указанную операцию ввода-вывода.
Если f возвращает ошибку WouldBlock, состояние готовности, связанное с этим файловым дескриптором, сбрасывается, а метод возвращает Err(TryIoError::WouldBlock). В этом случае обычно потребуется снова опрашивать AsyncFd.
Этот метод помогает поддерживать синхронизацию состояния готовности базового файлового дескриптора с состоянием готовности на стороне tokio, сбрасывая состояние на стороне tokio только при возникновении условия WouldBlock. Вызывающий код должен гарантировать, что f возвращает WouldBlock только в том случае, если файловый дескриптор, от которого произошёл этот AsyncFdReadyGuard, больше не находится в состоянии готовности, запрошенном при создании этого AsyncFdReadyGuard.
Примеры
В этом примере несколько байтов отправляются во внутренний std::net::UdpSocket. Ожидание готовности к записи и повторная попытка при блокировке операции отправки выполняются явно. Этот пример можно записать лаконичнее, используя 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(())
}Реализации трейтов
Автоматические реализации трейтов
impl<'a, T> !RefUnwindSafe for AsyncFdReadyGuard<'a, T>
impl<'a, T> !UnwindSafe for AsyncFdReadyGuard<'a, T>
impl<'a, T> Freeze 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> UnsafeUnpin for AsyncFdReadyGuard<'a, T>
Общие реализации
impl<T> BorrowMut<T> for Twhere T: ?Sized,
fn borrow_mut(&mut self) -> &mut T
impl<T> Instrument for T
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
impl<T> WithSubscriber for T
fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
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.AsyncFdReadyGuard.html