Я новичок в Rust, и я пытаюсь реализовать простое, потокобезопасное хранилище ключей и значений в памяти, используя HashMap
, защищенный в RwLock
. Мой код выглядит так:
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
, который не освобождается до тех пор, пока сам курсор не будет освобожден (в основном я не хочу разрешать модификации, пока курсор жив).
Я пробовал это:
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 | | }
| |_____^
Любые идеи?
Cursor
жив, вы хотите, чтобы никто другой не модифицировал вашHashMap
? Это цель всего этого? - person hellow   schedule 23.11.2018return
в качестве последнего оператора. Вместо этого просто удалитеreturn
и;
, например.fn foo() -> u32 { 3 }
- person hellow   schedule 23.11.2018return
для согласованности, поэтому я бы не назвал это однообразным; это просто вопрос личного стиля. - person Sven Marnach   schedule 23.11.2018return
в качестве последней строки функции работает, но считается плохим стилем: - person hellow   schedule 23.11.2018Cursor
? Если нет, это другой способ (возможно, не идеально) - person vikram2784   schedule 23.11.2018return
в последнем утверждении, но не очень понимаю, что должны делать другие люди. - person Sven Marnach   schedule 23.11.2018