gpt4 book ai didi

rust - Rust零拷贝生命周期处理

转载 作者:行者123 更新时间:2023-12-03 11:31:36 25 4
gpt4 key购买 nike

我正在尝试为Rust中的实时数据处理实现零拷贝机制。
为了说明我的问题,我准备了以下示例:

use std::io;

pub trait Producer<T> {
fn produce(&self) -> Result<T, ()>;
}

pub trait Consumer<T> {
fn consume(&self, t: T);
}

pub trait Source<T> : Producer<T> {
fn push(&self, t: T) -> io::Result<()>;
}

pub trait Sink<T> : Consumer<T> {
fn pull(&self) -> io::Result<T>;
}

pub struct SyncSource<T> {
pub producer: Option<Box<dyn Fn() -> T>>,
}

impl<T> SyncSource<T> {
pub fn new() -> SyncSource<T> {
SyncSource {
producer: None,
}
}
}

impl<T> Producer<T> for SyncSource<T> {
fn produce(&self) -> Result<T, ()> {
match &self.producer {
Some(func) => Ok((*(func))()),
None => Err(()),
}
}
}

impl<T> Source<T> for SyncSource<T> {
fn push(&self, t: T) -> io::Result<()> {
// do something useful
Ok(())
}
}

pub struct Frame<'a> {
pub buf: &'a [u8],
}

pub struct Capture {
buf: Vec<u8>,
}

impl Capture {
pub fn add(&mut self, val: u8) {
self.buf.push(val);
}

pub fn read(&self) -> Frame {
Frame {
buf: &self.buf[..],
}
}
}

fn main() {
let mut capture = Capture {
buf: Vec::new(),
};

let source: SyncSource<Frame> = SyncSource::new();

// immutable borrow of 'capture'
let frame = capture.read();

source.push(frame);

// mutable borrow of 'capture'
capture.add(1); // ERROR
}

..当然会产生借阅检查器错误:
error[E0502]: cannot borrow `capture` as mutable because it is also borrowed as immutable
--> src/bin/so.rs:212:5
|
208 | let frame = capture.read();
| ------- immutable borrow occurs here
...
212 | capture.add(1);
| ^^^^^^^^^^^^^^ mutable borrow occurs here
213 | }
| - immutable borrow might be used here, when `source` is dropped and runs the destructor for type `SyncSource<'_, Frame<'_>>`

我知道 push(frame)在同一范围内不能有不可变的引用,而 capture.add(1)稍后需要使用可变引用。

我想要达到的目的是使 push(frame)能够对切片执行一些有用的操作(如有必要,还可以将其复制到Vec中),但可能对此不做任何事情。

基本上,一旦 frame被调用,我就需要确保 push(frame)的生命周期结束。然后,这将释放借用的 Capture引用,并且 capture.add(1)调用将成功,并且将获取适当的可变引用。

我的零复制要求要求不要将切片复制到Vec中,然后将新缓冲区交给 push(..)
我在这里想念什么?也许有一些显式的生命周期注释?

最佳答案

如何修复

创建一个新块,以确保在更改source之前删除不可变借位(capture):

Playground

let mut capture = Capture {
buf: Vec::new(),
};

{
let source: SyncSource<Frame> = SyncSource::new();

// immutable borrow of 'capture'
let frame = capture.read();

// borrow moved into `source`
source.push(frame);

// `source` dropped here
}

// mutable borrow of 'capture'
capture.add(1);

为什么NLL没有帮助

此问题应该用 non-lexical lifetimes(NLL)修复。但是,NLL不适用于实现 Drop特征的类型,因为 Drop总是在值的词法范围的末尾调用,以实现向后兼容。

由于 SyncSource包含一个特征对象( dyn Fn() -> T),它可以潜在地实现 Drop,因此在这种情况下可以防止NLL。在 this playground中,您可以看到除去trait对象可以修复错误,这要归功于NLL。

但是我想循环访问 sourcecapture!

然后,将可变且不可变的借用进行交织,这意味着Rust不能在编译时验证所有权规则。

您可以使用 RefCell来解决此问题,它可以确保在运行时维护所有权规则。可以这样实现:

use std::cell::{RefCell, Ref};

pub struct Frame<'a> {
pub buf: Ref<'a, Vec<u8>>,
}

pub struct Capture {
buf: RefCell<Vec<u8>>,
}

impl Capture {
pub fn add(&self, val: u8) {
self.buf.borrow_mut().push(val);
}

pub fn read(&self) -> Frame {
Frame {
buf: self.buf.borrow(),
}
}
}

关于rust - Rust零拷贝生命周期处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61371710/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com