如何从 RwLock-ed Struct 的 RefCell 内的 Hashmap 中删除项目

How to delete item from Hashmap inside a RefCell within an RwLock-ed Struct

提问人:Gman man 提问时间:8/5/2019 最后编辑:Peter HallGman man 更新时间:8/5/2019 访问量:276

问:

我有一个结构:

pub struct CommunityContents {
    pub friends: RefCell<HashMap<FriendID, FriendData>>, 
    pub index: RefCell<HashMap<u64, BTreeMap<FriendID, FriendData>>>, 
    pub authenticated: bool,
    pub age: u64,     
    pub height: u64,
}

它由具有父结构的 RwLock 保护:

pub struct Community {
    pub community_contents: RwLock<CommunityContents>,
}

pub struct FriendData {
    pointer: Rc<Data>,
}

pub struct Data {
    pub key: Key,
    pub friend_ids: Vec<FriendID>,
}

我希望能够修改里面的数据。我在索引中插入数据没有问题,对内部做 to 和 a 。indexwrite()CommunityContentsborrow_mut().insert(…)BtreeMapindex

我的问题是从 中删除元素,给定 .我的粗略尝试是:BtreeMapFriendID

pub fn delete_family(community: &Self, friend_id: FriendID) {
    //get community contents
    let mut g = community.community_contents.write().expect("Lock is poisoned");
    //get friend from inside friends name of community contents
    let mut friend = g.friends.borrow_mut().get(&friend_id).unwrap().pointer.clone();
    // get id attri
    let mut friend_key = friend.key;
    let mut a = g.index.borrow_mut().get(&friend_key);
    let mut c = a.unwrap();
    c.remove(&friend_id);
}

我得到错误不能借用为可变的。我尝试了各种方法,这使我上面的代码有点混乱。

编辑:对不起,我错过了问题中的和结构。FriendDataData

收集 可变 借贷

评论

0赞 Peter Hall 8/5/2019
请提供确切的错误。此外,请考虑删除与问题无关的字段和类型,以创建最小的可重现示例

答:

1赞 Peter Hall 8/5/2019 #1

在对示例代码中缺少的类型进行一些猜测后,我看到两个错误:

error[E0716]: temporary value dropped while borrowed
  --> src/lib.rs:37:21
   |
37 |         let mut a = g.index.borrow_mut().get(&friend_key);
   |                     ^^^^^^^^^^^^^^^^^^^^                 - temporary value is freed at the end of this statement
   |                     |
   |                     creates a temporary which is freed while still in use
38 |         let mut c = a.unwrap();
   |                     - borrow later used here
   |
   = note: consider using a `let` binding to create a longer lived value

error[E0596]: cannot borrow `*c` as mutable, as it is behind a `&` reference
  --> src/lib.rs:39:9
   |
38 |         let mut c = a.unwrap();
   |             ----- help: consider changing this to be a mutable reference: `&mut std::collections::BTreeMap<u64, FriendData>`
39 |         c.remove(&friend_key);
   |         ^ `c` is a `&` reference, so the data it refers to cannot be borrowed as mutable

第一个问题可以通过遵循建议来修复 - 使用一个新变量来确保临时值(在错误消息中下划线)的生存时间足够长:

let mut tmp = g.index.borrow_mut();
let mut a = tmp.get(&friend_key);

现在,借入的价值一直存在到功能的尽头,比需要从中借用的价值更长。tmpa

第二个错误和建议可能更难理解。 是一个,但在解包它之后,你正在尝试改变它,因此引用需要是可变的。来自对 的调用,因此您需要找到一种方法来获取可变引用。您可以使用不同的方法执行此操作,该方法将返回所需的:aOption<&BTreeMap>Option<&BTreeMap>getget_mutOption<&mut BTreeMap>

let mut tmp = g.index.borrow_mut();
let mut a = tmp.get_mut(&friend_key);

评论

0赞 Gman man 8/5/2019
这是完全有道理的,感谢您的解释澄清。如果您不介意,还有一件快速的事情,您认为结构上的 RwLock 使 RefCells 变得不必要吗?我想知道我在那里是不是矫枉过正了。