借用检查同步和异步代码之间的差异?

问题描述 投票:0回答:0

每次我认为我理解 Rust 的借用检查器时,我都会遇到这样的事情,这让我的大脑崩溃。

我正在使用包装 libpcap 的第三方库,其

Capture<Active>::next_packet()
调用将
&mut self
作为 arg 并返回
Packet
。如果在具有同步功能的循环中(
sync_no_problem()
,见下文),我存储这个数据包,借用检查器工作正常。但是,如果我采用 完全相同的代码 并在异步函数中运行它(
async_has_borrow_problem()
,如下),借用检查器会抱怨我无法重新借用与 &mut 相同的函数。具体错误:

error[E0499]: cannot borrow `cap` as mutable more than once at a time
   --> src/main.rs:249:19
    |
249 |         let pkt = cap.next_packet().unwrap();
    |                   ^^^^^^^^^^^^^^^^^ `cap` was mutably borrowed here in the previous iteration of the loop
250 |         let owned_pkt = pkt.clone();
251 |         captured.insert(1, owned_pkt);
    |         ----------------------------- first borrow used here, in later iteration of loop

如果我让一个异步函数(

nested_async_no_proble()
,如下)调用同步函数,真的很麻烦,借用检查器就可以了。有人可以向我解释这里发生了什么吗?

仅供参考:我试图简化示例以删除 pcap 引用,但我无法重现该问题,因此我认为这与它们的工作方式有关。我还在

.clone()
结构上尝试了丰富的
.to_owned()
Packet
认为可以解决问题,但事实并非如此。

use pcap::Capture;

fn sync_no_problem() {
    let captured = std::collections::HashMap::new();
    let cap = pcap::Device::lookup().unwrap().unwrap().open().unwrap();
    for i in 0..5 {
        let pkt = cap.next_packet().unwrap();
        captured.insert(1, pkt);
    }
    println!("{:?}", captured);
}

async fn async_has_borrowing_problem() {
    let mut captured = std::collections::HashMap::new();
    let mut cap = pcap::Device::lookup().unwrap().unwrap().open().unwrap();
    for i in 0..5 {
        let pkt = cap.next_packet().unwrap();
        let owned_pkt = pkt.clone();
        captured.insert(1, owned_pkt);
    }
    println!("{:?}", captured);
}

async fn nested_async_no_problem() {
    // this has no problems!!?
    sync_no_problem();
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    sync_no_problem();
    // calling this has problems
    // async_has_borrowing_problem().await;
    nested_async_no_problem().await;
}
rust pcap rust-tokio
© www.soinside.com 2019 - 2024. All rights reserved.