我有一个包含用于通信的TcpStream和用于接收数据的BytesMut的结构。当我需要使用它来接收数据时,我打算做以下工作。
#[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包装了另一部分,以获得内部可更改性。
#[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>类型的参数。
但我知道两者都不是可直接兑换的,我该怎么办?
发布于 2022-09-16 07:10:25
lock()方法不提供引用,而是提供MutexGuard。当多次使用这个保护时,我们借用它的次数是相同的,这可以引入您报告的问题。一种解决方案是只获得持有的引用一次( &mut *技巧,实际上是.deref_mut()),然后使用此引用多次,依赖于其他答案中所述的拆分借用。
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();
}
}发布于 2022-09-16 07:03:07
显然,这不能编译,因为tcps被借用了一次,而BytesMut (即read_buf() )参数又被硼化了。
这不是问题吗?锈蚀可以分裂借用,尽管有时你不得不稍微推一下它(可能取决于你正在使用的版本)。我想出了一个快速变体,它编译得很好。
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);
}发布于 2022-09-16 07:05:10
您可以借用Ctx,一种简单的方法是使用上下文的destructure版本:
#[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();
}
}https://stackoverflow.com/questions/73740842
复制相似问题