我在arc和rwlock相关的生命周期方面遇到了很多麻烦。
struct ComponentContainer<T>{
id_to_component: HashMap<uint, uint>,
components: Arc<RWLock<~Vec<T>>>
}
id_to_component是组件id到组件内部Vec索引的映射。
我已经尝试了所有的方法,从直观的:
impl<T: Component> ComponentContainer<T>{
fn get<'a>(&'a self, id: uint) -> &'a T {
let idx = self.id_to_component.get(&id);
self.components.read().get(*idx)
}
}
到极度冗长(手动存储每个引用):
impl<T: Component> ComponentContainer<T> {
fn get<'a>(&'a self, id: uint) -> &'a T {
let idx = self.id_to_component.get(&id);
let components: &'a RWLock<~Vec<T>> = &'a *self.components;
let c: &'a RWLock<~Vec<T>> = &'a *components;
let tmp: &'a RWLockReadGuard<'a, ~Vec<T>> = &'a c.read();
let v: &'a ~Vec<T> = &'a **tmp;
v.get(*idx)
}
}
对于冗长的那个,我最终得到错误:
error: borrowed value does not live long enough
let tmp: &'a RWLockReadGuard<'a, ~Vec<T>> = &'a c.read();
^~~~~~~~~~~~
根据RWLock.read()的源代码,返回的引用应该具有指定的生命周期,除非我读错了。
编辑:完整的rustc输出短版本
test.rs:18:9: 18:31 error: borrowed value does not live long enough
test.rs:18 self.components.read().get(*idx)
^~~~~~~~~~~~~~~~~~~~~~
test.rs:16:45: 19:6 note: reference must be valid for the lifetime &'a as defined on the block at 16:44...
test.rs:16 fn get<'a>(&'a self, id: uint) -> &'a T {
test.rs:17 let idx = self.id_to_component.get(&id);
test.rs:18 self.components.read().get(*idx)
test.rs:19 }
test.rs:16:45: 19:6 note: ...but borrowed value is only valid for the block at 16:44
test.rs:16 fn get<'a>(&'a self, id: uint) -> &'a T {
test.rs:17 let idx = self.id_to_component.get(&id);
test.rs:18 self.components.read().get(*idx)
test.rs:19 }
error: aborting due to previous error
看read()
的签名:
fn read<'a>(&'a self) -> RWLockReadGuard<'a>
返回一个RWLockReadGuard<'a>
。这不是对RWLockReadGuard
的引用,它是RWLockReadGuard
, 包含生命期'a
的引用。
现在你的行:
let tmp: &'a RWLockReadGuard<'a, ~Vec<T>> = &'a c.read();
您正在引用RWLockReadGuard
。这意味着被引用的对象必须至少与引用的存在时间一样长。但事实并非如此:该值是c.read()
返回的值,不存储在的任何地方。因为它不存储在任何地方,它在语句结束时被丢弃,所以借用是无效的,因为所需的'a
比语句长,因此无法满足。
你应该做的是简单地删除&'a
部分,直接使用对象:
let tmp: RWLockReadGuard<'a, ~Vec<T>> = c.read();
第一眼我不知道你的简短版本有什么问题,我手边没有生锈。