提问人:andreasppg 提问时间:10/27/2023 更新时间:10/28/2023 访问量:40
如何使用 BufReader 的fill_buff并通过 TcpStream 使用
How do I use BufReader's fill_buff and consume with TcpStream
问:
以下代码不编译
use std::io::{BufRead, BufReader};
use std::net::{TcpListener};
fn main() {
let listener = TcpListener::bind(format!("0.0.0.0:{}", 7007)).unwrap();
for stream in listener.incoming() {
let mut stream = stream.unwrap();
let mut buf_reader = BufReader::new(&mut stream);
let buf = buf_reader.fill_buf().unwrap();
buf_reader.consume(buf.len())
}
}
有错误:
error[E0499]: cannot borrow `buf_reader` as mutable more than once at a time
--> src/main.rs:10:9
|
9 | let buf = buf_reader.fill_buf().unwrap();
| --------------------- first mutable borrow occurs here
10 | buf_reader.consume(buf.len())
| ^^^^^^^^^^^^^^^^^^^---------^
| | |
| | first borrow later used here
| second mutable borrow occurs here
我不明白这与文档示例中使用的代码有何不同
答:
1赞
Jared Smith
10/28/2023
#1
该方法采用对结构的可变引用,因此这是一个可变的借用。该方法也采用与 does 相同的方法,因此如果编译器认为您仍然坚持使用第一个方法,则不行。fill_buf
consume
&mut self
fill_buf
在 Rust 中,可变引用是完全排他性的:你不能对同一个内存块持有多个可变引用。
你的代码和文档中的示例之间的区别在于,编译器在文档示例中知道你已经完成了(读取器的第一个可变借用),只要你占用了长度,它就可以释放“锁”,可以说,并在你调用时做好准备。buf
.consume
尽管从逻辑上讲,这两者应该是等价的,但请记住,Rust 编译器正在执行所有这些(非常复杂的)静态分析,以既为您管理内存资源,又保证一定程度的线程安全,而无需使用实际的锁,因此它在某种程度上受到源代码文本的限制, 而不是它的逻辑运行时语义。
只需按照 prog-fh 在评论中的建议执行操作,然后拆分调用:.len
let length = buf.len(); // compiler can now drop first mutable borrow because we don't use buf again
buf_reader.consume(length); // second &mut is now exclusive
评论
let amount = buf.len();
buf_reader.consume(amount);