gpt4 book ai didi

rust - Rust 中带有 RwLockGuard 的 HashMap 记录游标

转载 作者:行者123 更新时间:2023-11-29 07:59:23 24 4
gpt4 key购买 nike

我是 Rust 的新手,我正在尝试使用 RwLock 中保护的 HashMap 实现一个简单的、线程安全的内存键值存储。我的代码如下所示:

use std::sync::{ Arc, RwLock, RwLockReadGuard };
use std::collections::HashMap;
use std::collections::hash_map::Iter;

type SimpleCollection = HashMap<String, String>;

struct Store(Arc<RwLock<SimpleCollection>>);

impl Store {
fn new() -> Store { return Store(Arc::new(RwLock::new(SimpleCollection::new()))) }

fn get(&self, key: &str) -> Option<String> {
let map = self.0.read().unwrap();
return map.get(&key.to_string()).map(|s| s.clone());
}

fn set(&self, key: &str, value: &str) {
let mut map = self.0.write().unwrap();
map.insert(key.to_string(), value.to_string());
}
}

到目前为止,这段代码工作正常。问题是我正在尝试实现一个 scan() 函数,该函数返回一个 Cursor 对象,该对象可用于遍历所有记录。我希望 Cursor 对象持有一个 RwLockGuard,它在游标本身被释放之前不会被释放(基本上我不想在 Cursor 存在时允许修改) .

我试过这个:

use ...

type SimpleCollection = HashMap<String, String>;

struct Store(Arc<RwLock<SimpleCollection>>);

impl Store {
...

fn scan(&self) -> Cursor {
let guard = self.0.read().unwrap();
let iter = guard.iter();
return Cursor { guard, iter };
}
}

struct Cursor<'l> {
guard: RwLockReadGuard<'l, SimpleCollection>,
iter: Iter<'l, String, String>
}

impl<'l> Cursor<'l> {
fn next(&mut self) -> Option<(String, String)> {
return self.iter.next().map(|r| (r.0.clone(), r.1.clone()));
}
}

但这没有用,因为我遇到了这个编译错误:

error[E0597]: `guard` does not live long enough
--> src/main.rs:24:20
|
24 | let iter = guard.iter();
| ^^^^^ borrowed value does not live long enough
25 | return Cursor { guard, iter };
26 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the anonymous lifetime #1 defined on the method body at 22:5...
--> src/main.rs:22:5
|
22 | / fn scan(&self) -> Cursor {
23 | | let guard = self.0.read().unwrap();
24 | | let iter = guard.iter();
25 | | return Cursor { guard, iter };
26 | | }
| |_____^

有什么想法吗?

最佳答案

如评论中所述,问题在于 structs generally can't be self-referential in Rust 。您尝试构造的 Cursor 结构包含 MutexGuard 和借用 MutexGuard 的迭代器,这是不可能的(有充分的理由 - 请参阅链接的问题)。

在这种情况下,最简单的解决方法是引入一个单独的结构来存储 MutexGuard,例如

struct StoreLock<'a> {
guard: RwLockReadGuard<'a, SimpleCollection>,
}

Store 上,我们可以引入一个返回 StoreLock 的方法

fn lock(&self) -> StoreLock {
StoreLock { guard: self.0.read().unwrap() }
}

StoreLock 可以公开实际的 scan() 方法(可能还有其他需要持久锁的方法):

impl<'a> StoreLock<'a> {
fn scan(&self) -> Cursor {
Cursor { iter: self.guard.iter() }
}
}

Cursor 结构本身只包含迭代器:

struct Cursor<'a> {
iter: Iter<'a, String, String>,
}

客户端代码首先需要获取锁,然后获取游标:

let lock = s.lock();
let cursor = lock.scan();

这确保了锁的生命周期足以完成扫描。

Full code on the playground

关于rust - Rust 中带有 RwLockGuard 的 HashMap 记录游标,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53439726/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com