如何在互斥体内的数据上返回迭代器,互斥体本身包含在结构中.编译器给出的错误是"借来的价值不够长".
如何将值的生命周期延伸到外部范围?
这是我想要实现的最小演示.
use std::sync::{Mutex, Arc};
use std::vec::{Vec};
use std::slice::{Iter};
#[derive(Debug)]
struct SharedVec {
pub data: Arc<Mutex<Vec<u32>>>,
}
impl SharedVec {
fn iter(& self) -> Iter<u32> {
self.data.lock().unwrap().iter()
}
}
fn main() {
let sv = SharedVec {
data: Arc::new(Mutex::new(vec![1, 2, 3, 4, 5]))
};
for element in sv.data.lock().unwrap().iter() { // This works
println!("{:?}", element);
}
for element in sv.iter() { // This does not work
println!("{:?}", element);
}
}
Run Code Online (Sandbox Code Playgroud)
Rust操场链接:http://is.gd/voukyN
你不能完全按照你在这里写的方式去做.
Rust中的互斥锁使用RAII模式进行获取和释放,也就是说,当您在其上调用返回特殊保护值的相应方法时,您将获得互斥锁.当此防护超出范围时,将释放互斥锁.
为了使这种模式安全,Rust使用其借用系统.您只能通过返回的后卫访问值的互斥体lock(),你只可以参考这样做- MutexGuard<T>器具Deref<Target=T>和DerefMut<Target=T>,这样你就可以得到&T或&mut T出来.
这意味着您从互斥值中获得的每个值都必须将其生命周期与守卫的生命周期相关联.但是,在您的情况下,您尝试返回Iter<u32>其生命周期参数与生命周期相关联self.以下是iter()方法的完整签名,没有生命周期参数省略,并且其主体具有显式临时变量:
fn iter<'a>(&'a self) -> Iter<'a, u32> {
let guard = self.data.lock().unwrap();
guard.iter()
}
Run Code Online (Sandbox Code Playgroud)
这里guard.iter()结果的生命周期与一个相关联guard,它严格地小于'a因为guard只存在于方法体的范围内.这违反了借用规则,因此编译器失败并出现错误.
当iter()返回,guard被销毁并且锁被释放时,Rust实际上阻止了您发出实际的逻辑错误!C++中的相同代码将编译和行为不正确,因为您将访问受保护的数据而不锁定它,至少导致数据争用.再一次证明了Rust的力量:)
如果没有标准类型的讨厌的黑客或样板包装,我认为你不能做你想要的.我个人认为这很好 - 您必须尽可能明确地管理您的互斥锁,以避免死锁和其他令人讨厌的并发问题.Rust已经让你的生活变得更加轻松,因为它通过借用系统强制缺少数据竞争,这正是防护系统如上所述行为的原因.