【问题标题】:AsyncRead wrapper over sync read同步读取上的 AsyncRead 包装器
【发布时间】:2021-09-11 18:49:57
【问题描述】:

我在通过同步读取实现 AsyncRead 以适应 Rust 中的异步世界时遇到了这个问题。

我正在处理的同步读取实现是原始 C 同步实现的包装,很像 std::fs::File::read;因此,为了简单起见,我以后会使用std::io::Read

代码如下:

use futures::{AsyncRead, Future};
use std::task::{Context, Poll};
use std::pin::Pin;
use tokio::task;
use std::fs::File;
use std::io::Read;
use std::io::Result;

struct FileAsyncRead {
    path: String
}

impl AsyncRead for FileAsyncRead {
    fn poll_read(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut [u8]) -> Poll<Result<usize>> {
        let path = self.path.to_owned();
        let buf_len = buf.len();
        let mut handle = task::spawn_blocking(move || {
            let mut vec = vec![0u8; buf_len];
            let mut file = File::open(path).unwrap();
            let len = file.read(vec.as_mut_slice());
            (vec, len)
        });

        match Pin::new(&mut handle).poll(cx) {
            Poll::Ready(l) => {
                let v_l = l.unwrap();
                let _c_l = v_l.0.as_slice().read(buf);
                Poll::Ready(v_l.1)
            }
            Poll::Pending => Poll::Pending
        }
    }
}

当前的实现是每次都创建一个与外部buf: &amp;mut [u8]相同大小的新向量,因为:

`buf` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement

 buf: &mut [u8],
    |                --------- this data with an anonymous lifetime `'_`...

我的问题是:

  1. 是否可以避免在spwan_blocking 中创建向量并在poll_read 中改变buf?避免向量分配和复制?
  2. 有没有比spawn_blockingPin::new(&amp;mut handle).poll(cx) 更好的方法来表达这个“包装器”逻辑?在 Rust 中,更惯用的方法是什么?

【问题讨论】:

  • 哪个版本的 tokio?我有点困惑,因为here 它有 tokio::io::ReadBuf 而不是 [u8]

标签: rust rust-tokio


【解决方案1】:

这段代码有些奇怪:

  1. 如果此代码被调用一次,它可能会返回 Poll::Pending,因为 spawn_blocking 甚至需要时间来启动任务。
  2. 如果这被多次调用,那么它会创建多个不相关的任务来读取文件的同一部分,并可能由于 (1) 而忽略结果,这可能不是您想要的。

解决此问题的方法是在第一次创建 FileAsyncRead 结构时记住该任务,然后在下一次调用时仅在需要时启动新任务,并轮询现有任务。

使用此 API,您似乎无法避免双重缓冲,因为您的 API 是阻塞的,并且 ReadBuf 缓冲区未共享,您需要对其他缓冲区进行阻塞读取,然后复制当一个新的非阻塞调用poll_read() 到达时数据结束。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多