如何制作一个变异迭代器来锁定内部数据直到删除?

问题描述 投票:0回答:1

我的目标是使用

NewType(Arc<RwLock<Vec<T>>>)
方法创建一个
many_iter_mut()
,该方法返回一个迭代器,该迭代器在内部
RwLockWriteGuard
上持有写锁 (
Vec<T>
)。

因此,写锁将由

ManyIterMut
迭代器保持,直到迭代器被删除。这与每次调用
ManyIterMut::next()
时获取写锁不同。 (我已经在其他地方工作过)

这对于使调用者能够同时但原子地设置许多元素和读取许多元素很有用。这样读者总是会看到从一批写入到下一批写入的一致视图。 (我之前的

ManyIterMut
实现未能通过并发测试。)

问题是由于生命周期问题,我无法编译

ManyIterMut::next()
方法。编译器似乎不喜欢
write_lock
属于
ManyIterMut
而不是正在迭代的
LockedVec

这里是游乐场

产生错误的代码是:

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

那么,我错过了什么?看起来应该是可以的。或者有更简单的方法吗?

multithreading rust iterator
1个回答
0
投票
write_lock: &'c mut RwLockWriteGuard<'c, V::LockedData>,

这种模式(

&'a mut T<'a>
)(几乎?)总是错误的。 At 允许使用数据最多一次。请参阅永远借用一些东西 了解更多。

解决方案是引入另一个生命周期。这需要一些修复,主要是在

type Item<'b> = StorageSetter<'b, V, T>
将其更改为
type Item<'b> = StorageSetter<'a, 'b, V, T>

© www.soinside.com 2019 - 2024. All rights reserved.