我的目标是用一个many_iter_mut()
方法生成一个NewType(Arc<RwLock<Vec<T>>>)
,该方法返回一个迭代器,该迭代器在内部Vec<T>
上持有写锁(RwLockWriteGuard
).
因此,写锁将由ManyIterMut
迭代器保持,直到迭代器被删除.这不同于每次调用ManyIterMut::next()
时都获得写锁定.(我已经在其他地方工作过了)
这对于使调用者能够同时设置多个元素和读取多个元素非常有用,但是是原子性的. 这样读者就可以看到从一批写入到下一批写入的一致视图. (我之前的ManyIterMut
impl没有通过并发测试.
问题是,由于生命周期的问题,我无法编译ManyIterMut::next()
方法.编译器似乎不喜欢write_lock
由ManyIterMut
拥有,而不是被迭代的LockedVec
拥有.
给你playground块.
生成错误的代码为:
impl<'a, V, T: 'a> LendingIterator for ManyIterMut<'a, V, T>
where
V: StorageVecWrites<T> + ?Sized,
V::LockedData: StorageVecReads<T>,
T: Copy,
{
type Item<'b> = StorageSetter<'b, V, T>
where
Self: 'b;
// This is the fn that won't compile.
//
// we can't change the fn signature, it is defined by lending_iterator::LendingIterator trait.
fn next(&mut self) -> Option<Self::Item<'_>> {
if let Some(i) = Iterator::next(&mut self.indices) {
let value = self.write_lock.get_at(i).unwrap();
Some(StorageSetter {
phantom: Default::default(),
write_lock: &mut self.write_lock, // <--- this seems to be the problem. Because it has &mut self lifetime, not Self::Item<'_> lifetime
index: i,
value,
})
} else {
None
}
}
}
错误是:
error: lifetime may not live long enough
--> src/main.rs:164:13
|
148 | impl<'a, V, T: 'a> LendingIterator for ManyIterMut<'a, V, T>
| -- lifetime `'a` defined here
...
161 | fn next(&mut self) -> Option<Self::Item<'_>> {
| - let's call the lifetime of this reference `'1`
...
164 | / Some(StorageSetter {
165 | | phantom: Default::default(),
166 | | write_lock: &mut self.write_lock, // <--- this seems to be the problem. Because it has &mut self lifetime, not Self::It...
167 | | index: i,
168 | | value,
169 | | })
| |______________^ method was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1`
|
= note: requirement occurs because of the type `StorageSetter<'_, V, T>`, which makes the generic argument `'_` invariant
= note: the struct `StorageSetter<'c, V, T>` is invariant over the parameter `'c`
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
error: could not compile `playground` (bin "playground") due to previous error
我错过了什么? 似乎应该可以. 还是有更简单的方法