首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何解决在锈蚀中借款不止一次的问题?

如何解决在锈蚀中借款不止一次的问题?
EN

Stack Overflow用户
提问于 2022-09-16 06:38:44
回答 3查看 73关注 0票数 1

我有一个包含用于通信的TcpStream和用于接收数据的BytesMut的结构。当我需要使用它来接收数据时,我打算做以下工作。

代码语言:javascript
复制
#[tokio::test]
async fn test_refmut1() {
    struct Ctx {
        tcps: TcpStream,
        data: BytesMut,
    }
    async fn recv(ctx: Arc<Mutex<Ctx>>) {
        let mut ctx = ctx.lock().await;
        ctx.tcps.read_buf(&mut ctx.data).await.unwrap();
    }
}

显然,这不能编译,因为tcps被借用了一次,而BytesMut ( read_buf()参数)再次被轮询。

与往常一样,我使用RefCell包装了另一部分,以获得内部可更改性。

代码语言:javascript
复制
#[tokio::test]
async fn test_refmut2() {
    struct Ctx {
        tcps: TcpStream,
        data: RefCell<BytesMut>,
    }
    
    async fn recv(ctx: Arc<Mutex<Ctx>>) {
        let mut ctx = ctx.lock().await;
        let tcps = &ctx.tcps;
        let mut data = ctx.data.borrow_mut();
        ctx.tcps.read_buf(&data).await.unwrap();
    }
}

但是,这仍然不能编译,因为read_buf()需要一个类型为&mut BytesMut的参数,我现在通过RefCell借用这个参数作为RefMut<BytesMut>类型的参数。

但我知道两者都不是可直接兑换的,我该怎么办?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2022-09-16 07:10:25

lock()方法不提供引用,而是提供MutexGuard。当多次使用这个保护时,我们借用它的次数是相同的,这可以引入您报告的问题。一种解决方案是只获得持有的引用一次( &mut *技巧,实际上是.deref_mut()),然后使用此引用多次,依赖于其他答案中所述的拆分借用。

代码语言:javascript
复制
async fn test_refmut1() {
    struct Ctx {
        tcps: TcpStream,
        data: BytesMut,
    }
    async fn recv(ctx: Arc<Mutex<Ctx>>) {
        let mut ctx_guard = ctx.lock().await;
        let ctx = &mut *ctx_guard;
        ctx.tcps.read_buf(&mut ctx.data).await.unwrap();
    }
}
票数 2
EN

Stack Overflow用户

发布于 2022-09-16 07:03:07

显然,这不能编译,因为tcps被借用了一次,而BytesMut (即read_buf() )参数又被硼化了。

这不是问题吗?锈蚀可以分裂借用,尽管有时你不得不稍微推一下它(可能取决于你正在使用的版本)。我想出了一个快速变体,它编译得很好。

代码语言:javascript
复制
use std::io::*;

struct Ctx {
    tcps: Stdin,
    data: Vec<u8>,
}

fn recv(mut ctx: Ctx) {
    ctx.tcps.read_to_end(&mut ctx.data).unwrap();
}

fn main() {
    let ctx = Ctx { tcps: stdin(), data: Vec::new() };
    recv(ctx);
}
票数 1
EN

Stack Overflow用户

发布于 2022-09-16 07:05:10

您可以借用Ctx,一种简单的方法是使用上下文的destructure版本:

代码语言:javascript
复制
#[tokio::test]
async fn test_refmut1() {
    struct Ctx {
        tcps: TcpStream,
        data: BytesMut,
    }
    impl Ctx {
        async fn read(&mut self) {
            let Self { tcps, data } = self;
            tcps.read(data).await.unwrap();
        }
    }
    async fn recv(ctx: Arc<Mutex<Ctx>>) {
        let mut ctx = ctx.lock().await;
        ctx.read();
    }
}

游乐场

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73740842

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档