这里是一个假设的套接字的代码(playground here),当收到一些数据时,它将写回数据(如闭包中定义)。
pub struct Socket {
on_message_received: Box<dyn FnMut(&Vec<u8>, &mut Socket)>,
}
impl Socket {
pub fn new(on_message_received: Box<dyn FnMut(&Vec<u8>, &mut Socket)>) -> Self {
Self {
on_message_received,
}
}
pub fn read(&mut self, fake_data: &Vec<u8>) {
(self.on_message_received)(fake_data, self);
}
pub fn write(&mut self, data: Vec<u8>) {
println!(
"Pretend this requires a mutable reference to self {:?}",
data
);
}
}
fn main() {
let mut socket = Socket::new(Box::new(|data, socket| {
socket.write(data.clone());
}));
socket.read(&vec![1, 2, 3]);
}
行
(self.on_message_received)(fake_data, self);
无法编译,因为我们cannot borrow
*self as mutable more than once at a time
。我理解这一点,但想不出解决方法。
我还尝试过(其他playground)在setter中(而不是在构造函数中)定义闭包,并使闭包捕获对套接字的引用(而不是让闭包通过对套接字的引用来调用) ).
但最终,我总是面临同样的问题,即发生可变引用的双重借用。 🤔
如果你可以使用
Fn
而不是 FnMut
那么你可以通过使用 Arc
而不是 Box
来解决这个问题,并在调用闭包之前克隆 Arc
:
use std::sync::Arc;
pub struct Socket {
on_message_received: Arc<dyn Fn(&Vec<u8>, &mut Socket)>,
}
impl Socket {
pub fn new(on_message_received: Arc<dyn Fn(&Vec<u8>, &mut Socket)>) -> Self {
Self {
on_message_received,
}
}
pub fn read(&mut self, fake_data: &Vec<u8>) {
let cb = self.on_message_received.clone();
(cb)(fake_data, self);
}
pub fn write(&mut self, data: Vec<u8>) {
println!(
"Pretend this requires a mutable reference to self {:?}",
data
);
}
}
fn main() {
let mut socket = Socket::new(Arc::new(|data, socket| {
socket.write(data.clone());
}));
socket.read(&vec![1, 2, 3]);
}
(游乐场)
通过克隆
Arc
,我们获得了闭包的句柄,该句柄独立于 self
的生命周期,因此不需要借用 self
。
值得注意的是,这种方法允许
Socket::read
完全可重入——闭包可以毫无问题地调用 socket.read()
(当然,除了无限递归的可能性之外)。