Структура Unblock
Источник: Документация blocking::Unblock
#![allow(unused)] fn main() { pub struct Unblock<T> { /* private fields */ } }
Выполняет блокирующий I/O в пуле потоков.
Описание
Блокирующий I/O должен быть изолирован от асинхронного кода. Этот тип перемещает блокирующие I/O операции в специальный пул потоков, предоставляя при этом знакомый асинхронный интерфейс.
Этот тип реализует трейты Stream, AsyncRead, AsyncWrite или AsyncSeek, если внутренний тип реализует Iterator, Read, Write или Seek соответственно.
Особенности
Unblock является низкоуровневым примитивом и имеет некоторые ограничения:
Для более высокоуровневых примитивов, построенных на основе Unblock, используйте async-fs или async-process (на Windows).
Unblock взаимодействует с I/O операциями в пуле потоков через канал (pipe). Это означает, что асинхронная операция чтения/записи просто получает/отправляет некоторые байты из/в канал. В режиме чтения пул потоков читает байты из I/O дескриптора и пересылает их в канал, пока он не заполнится. В режиме записи пул потоков читает байты из канала и пересылает их в I/O дескриптор.
Используйте Unblock::with_capacity() для настройки емкости канала.
Предупреждения
Чтение
Если вы создадите Unblock<Stdin>, прочитаете из него некоторые байты, а затем удалите его, заблокированная операция чтения может продолжать висеть в пуле потоков. Следующая попытка чтения из stdin потеряет байты, прочитанные висящей операцией. Это сложная проблема для решения, поэтому убедитесь, что вы используете только один дескриптор stdin в течение всей программы.
Запись
Если вы записываете данные через трейт AsyncWrite, убедитесь, что выполнили сброс (flush) перед удалением дескриптора Unblock, иначе некоторые буферизированные данные могут быть потеряны.
Поиск (Seeking)
Из-за буферизации в канале, если Unblock оборачивает File, одна операция чтения может переместить курсор файла дальше, чем диапазон операции. Фактически, чтение просто продолжается в фоновом режиме, пока канал не заполнится. Имейте это в виду при использовании AsyncSeek с относительными смещениями.
Примеры
#![allow(unused)] fn main() { use blocking::Unblock; use futures_lite::prelude::*; let mut stdout = Unblock::new(std::io::stdout()); stdout.write_all(b"Hello world!").await?; stdout.flush().await?; }
Методы
Создание
| Метод | Сигнатура | Описание |
|---|---|---|
new | pub fn new(io: T) -> Unblock<T> | Оборачивает блокирующий I/O дескриптор в асинхронный интерфейс Unblock |
with_capacity | pub fn with_capacity(cap: usize, io: T) -> Unblock<T> | Оборачивает с пользовательской емкостью буфера |
Управление
| Метод | Сигнатура | Описание |
|---|---|---|
get_mut | pub async fn get_mut(&mut self) -> &mut T | Получает изменяемую ссылку на блокирующий I/O дескриптор |
with_mut | pub async fn with_mut<R, F>(&mut self, op: F) -> R | Выполняет блокирующую операцию над I/O дескриптором |
into_inner | pub async fn into_inner(self) -> T | Извлекает внутренний блокирующий I/O дескриптор |
Примеры использования
Базовое использование
#![allow(unused)] fn main() { use blocking::Unblock; let stdin = Unblock::new(std::io::stdin()); }
Настройка емкости буфера
#![allow(unused)] fn main() { use blocking::Unblock; let stdout = Unblock::with_capacity(64 * 1024, std::io::stdout()); }
Работа с дескриптором
#![allow(unused)] fn main() { use blocking::{unblock, Unblock}; use std::fs::File; let file = unblock(|| File::create("file.txt")).await?; let mut file = Unblock::new(file); // Получение ссылки на дескриптор let metadata = file.get_mut().await.metadata()?; // Выполнение операции над дескриптором let metadata = file.with_mut(|f| f.metadata()).await?; // Извлечение дескриптора let file = file.into_inner().await; }
Реализации трейтов
AsyncRead
Реализован для T: Read + Send + 'static:
poll_read()- попытка чтения в буферpoll_read_vectored()- векторизованное чтение
AsyncWrite
Реализован для T: Write + Send + 'static:
poll_write()- попытка записи из буфераpoll_flush()- сброс буферовpoll_close()- закрытие объектаpoll_write_vectored()- векторизованная запись
AsyncSeek
Реализован для T: Seek + Send + 'static:
poll_seek()- перемещение по потоку
Stream
Реализован для T: Iterator + Send + 'static:
poll_next()- получение следующего значенияsize_hint()- информация о размере
Другие трейты
Debug- дляT: DebugSend/Sync- при соответствующих ограничениях наTUnpin- можно перемещать после закрепления
Емкости по умолчанию
- Для типов
Iterator: 8192 элементов - Для типов
Read/Write: 8 МБ
Безопасность
!RefUnwindSafe- не безопасен для размотки через ссылку!UnwindSafe- не безопасен для размоткиFreeze- может быть заморожен