Struct blocking::Unblock[][src]

pub struct Unblock<T> { /* fields omitted */ }

Runs blocking I/O on a thread pool.

Blocking I/O must be isolated from async code. This type moves blocking I/O operations onto a special thread pool while exposing a familiar async interface.

This type implements traits Stream, AsyncRead, AsyncWrite, or AsyncSeek if the inner type implements Iterator, Read, Write, or Seek, respectively.

Caveats

Unblock is a low-level primitive, and as such it comes with some caveats.

For higher-level primitives built on top of Unblock, look into async-fs or async-process (on Windows).

Unblock communicates with I/O operations on the thread pool through a pipe. That means an async read/write operation simply receives/sends some bytes from/into the pipe. When in reading mode, the thread pool reads bytes from the I/O handle and forwards them into the pipe until it becomes full. When in writing mode, the thread pool reads bytes from the pipe and forwards them into the I/O handle.

Use Unblock::with_capacity() to configure the capacity of the pipe.

Reading

If you create an Unblock<Stdin>, read some bytes from it, and then drop it, a blocked read operation may keep hanging on the thread pool. The next attempt to read from stdin will lose bytes read by the hanging operation. This is a difficult problem to solve, so make sure you only use a single stdin handle for the duration of the entire program.

Writing

If writing data through the AsyncWrite trait, make sure to flush before dropping the Unblock handle or some buffered data might get lost.

Seeking

Because of buffering in the pipe, if Unblock wraps a File, a single read operation may move the file cursor farther than is the span of the operation. In fact, reading just keeps going in the background until the pipe gets full. Keep this mind when using AsyncSeek with relative offsets.

Examples

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?;

Implementations

impl<T> Unblock<T>[src]

pub fn new(io: T) -> Unblock<T>[src]

Wraps a blocking I/O handle into the async Unblock interface.

Examples

use blocking::Unblock;

let stdin = Unblock::new(std::io::stdin());

pub fn with_capacity(cap: usize, io: T) -> Unblock<T>[src]

Wraps a blocking I/O handle into the async Unblock interface with a custom buffer capacity.

When communicating with the inner Stream/Read/Write type from async code, data transferred between blocking and async code goes through a buffer of limited capacity. This constructor configures that capacity.

The default capacity is:

Examples

use blocking::Unblock;

let stdout = Unblock::with_capacity(64 * 1024, std::io::stdout());

pub async fn get_mut(&mut self) -> &mut T[src]

Gets a mutable reference to the blocking I/O handle.

This is an async method because the I/O handle might be on the thread pool and needs to be moved onto the current thread before we can get a reference to it.

Examples

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()?;

pub async fn with_mut<R, F>(&mut self, op: F) -> R where
    F: FnOnce(&mut T) -> R + Send + 'static,
    R: Send + 'static,
    T: Send + 'static, 
[src]

Performs a blocking operation on the I/O handle.

Examples

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.with_mut(|f| f.metadata()).await?;

pub async fn into_inner(self) -> T[src]

Extracts the inner blocking I/O handle.

This is an async method because the I/O handle might be on the thread pool and needs to be moved onto the current thread before we can extract it.

Examples

use blocking::{unblock, Unblock};
use futures_lite::prelude::*;
use std::fs::File;

let file = unblock(|| File::create("file.txt")).await?;
let file = Unblock::new(file);

let file = file.into_inner().await;

Trait Implementations

impl<T: Read + Send + 'static> AsyncRead for Unblock<T>[src]

impl<T: Seek + Send + 'static> AsyncSeek for Unblock<T>[src]

impl<T: Write + Send + 'static> AsyncWrite for Unblock<T>[src]

impl<T: Debug> Debug for Unblock<T>[src]

impl<T: Iterator + Send + 'static> Stream for Unblock<T> where
    T::Item: Send + 'static, 
[src]

type Item = T::Item

Values yielded by the stream.

Auto Trait Implementations

impl<T> !RefUnwindSafe for Unblock<T>

impl<T> Send for Unblock<T> where
    T: Send

impl<T> Sync for Unblock<T> where
    T: Sync

impl<T> Unpin for Unblock<T>

impl<T> !UnwindSafe for Unblock<T>

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<R> AsyncReadExt for R where
    R: AsyncRead + ?Sized
[src]

impl<S> AsyncSeekExt for S where
    S: AsyncSeek + ?Sized
[src]

impl<W> AsyncWriteExt for W where
    W: AsyncWrite + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<S> StreamExt for S where
    S: Stream + ?Sized
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

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

The type returned in the event of a conversion error.

impl<S, T, E> TryStream for S where
    S: Stream<Item = Result<T, E>> + ?Sized
[src]

type Ok = T

The type of successful values yielded by this future

type Error = E

The type of failures yielded by this future