固定位置缓冲器是Pin的一个很好的用例吗



我正在编写一些代码,在Rust和Linux内核之间共享缓冲区。注册缓冲区后,其内存位置不应移动。由于API采用*mut u8(实际上是libc::iovec(,但不强制执行固定内存位置约束,因此如果我将缓冲区表示为RefCell<Vec<u8>>Arc<RefCell<Vec<u8>>>Arc<Mutex<Vec<u8>>>,则它可以正常工作。(但Rust代码实际上从未写入缓冲区。(

在这个用例中,Pin是否提供了针对数据移动的额外安全性?我认为可能不会,因为其中一个主要风险是调用resize()并增长矢量,但我确实打算在不增长矢量的情况下调用resize()。代码是有效的,但我对以最正确的方式编写它感兴趣。

我真的不知道Pin,但它对自引用结构和协同程序AFAIK非常有用。

对于您的情况,我只想创建一个结构,强制执行数据移动的不变量。例如:

use std::ops::{Deref, DerefMut};
struct MyData{
data: Vec<u8>,
}
impl MyData{
fn with_capacity(cap: usize)->Self{
Self{data: Vec::with_capacity(cap)}
}
fn resize(&mut self, new_len: usize, val_to_set: u8){
let old_ptr = self.data.as_ptr();
// Enforce invariant that memory never moves.
assert!(new_len <= self.data.capacity());
self.data.resize(new_len, val_to_set);
debug_assert_eq!(old_ptr, self.data.as_ptr());
}
}
// To get access to bytes
impl Deref for MyData{
type Target = [u8];

fn deref(&self)->&[u8]{
&*self.data
}
}
impl DerefMut for MyData{
fn deref_mut(&mut self)->&mut[u8]{
&mut *self.data
}
}

此结构强制字节在不涉及Pin的情况下永远不会移动。

您可以将其包装到RefCell中。

最新更新