【发布时间】: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: &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 `'_`...
我的问题是:
- 是否可以避免在
spwan_blocking中创建向量并在poll_read中改变buf?避免向量分配和复制? - 有没有比
spawn_blocking和Pin::new(&mut handle).poll(cx)更好的方法来表达这个“包装器”逻辑?在 Rust 中,更惯用的方法是什么?
【问题讨论】:
-
哪个版本的 tokio?我有点困惑,因为here 它有 tokio::io::ReadBuf 而不是 [u8]
标签: rust rust-tokio