替换RwLockWriteGuard的内容

时间:2018-11-10 08:09:23

标签: rust

让我们假设以下代码:

use std::sync::RwLock;

pub struct NotCloneable(u8);

pub struct Foo {
    value: RwLock<Vec<NotCloneable>>,
}

impl Foo {
    // does not work
    pub fn filter_out_values(&self) {
        let mut guard = self.value.write().unwrap();
        *guard = guard.into_iter().filter(|nc| nc.0 != 0).collect();
    }
}
error[E0507]: cannot move out of borrowed content
  --> src/lib.rs:12:18
   |
12 |         *guard = guard.into_iter().filter(|nc| nc.0 != 0).collect();
   |                  ^^^^^ cannot move out of borrowed content

playground

如何使功能filter_out_values工作?

1 个答案:

答案 0 :(得分:4)

这里的特殊情况是您的T是不可克隆的,因此您不能使用guard.iter().filter(...).cloned().collect()

我在这里看到两个选择。

  1. 您可以使用RwLock<Vec<NotCloneable>>代替RwLock<Option<Vec<NotCloneable>>>,然后使用Option::take()来获取RwLock持有并离开None的值

  2. 您可以使用std::mem::replace()从防护中获取vec而不会触发错误,因为您无法将RwLock的值保持在未定义状态,即没有任何值

use std::sync::RwLock;

pub struct NotCloneable(u8);

pub struct Foo {
    value: RwLock<Vec<NotCloneable>>,
}

impl Foo {
    pub fn filter_out_values(&self) {
        let mut guard = self.value.write().unwrap();
        let vec = std::mem::replace(&mut *guard, vec![]);
        *guard = vec.into_iter().filter(|nc| nc.0 != 0).collect();
    }
}

pub struct Foo1 {
    value: RwLock<Option<Vec<NotCloneable>>>,
}

impl Foo1 {
    pub fn filter_out_values(&self) {
        let mut guard = self.value.write().unwrap();
        let vec = guard.take();
        *guard = Some(vec.unwrap().into_iter().filter(|nc| nc.0 != 0).collect());
    }
}

playground