I have a RwLock with map of more RwLocks inside. All was well until I wanted to have a general function: "obtain the inner lock, and call the real function with the inner lock's guard".
Why "map_guard" doesn't live long enough? Is this a problem solved with specifying some lifetimes or a lost cause?
use std::collections::HashMap;
use std::future::Future;
use tokio::sync::{RwLock, RwLockWriteGuard};
#[derive(Debug)]
struct Data {
pub x: u32
}
type State = RwLock<HashMap<u32, RwLock<Data>>>;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let mut map = HashMap::new();
map.insert(0, RwLock::new(Data{ x: 1}));
let state = RwLock::new(map);
execute_with_lock(&state, do_sth1,0).await;
Ok(())
}
async fn execute_with_lock<'a, 'b, 'c, X, F, Fut>(
state: &'a State, f: F, key: u32
) -> Option<X>
where
F: Fn(&'b RwLockWriteGuard<'c, Data>) -> Fut,
Fut: Future<Output=X>,
'a: 'c,
'c: 'b
{
let map_guard = state.read().await;
if let Some(data_lock) = map_guard.get(&key) {
let data_guard = data_lock.write().await;
Some(f(&data_guard).await)
} else {
None
}
}
async fn do_sth1<'a, 'b>(data_guard: &'a RwLockWriteGuard<'b, Data>) {
println!("data {}", data_guard.x)
}
The error is:
error[E0597]: `map_guard` does not live long enough
--> src/bin/test.rs:33:30
|
23 | async fn execute_with_lock<'a, 'b, 'c, X, F, Fut>(
| -- lifetime `'c` defined here
...
32 | let map_guard = state.read().await;
| --------- binding `map_guard` declared here
33 | if let Some(data_lock) = map_guard.get(&key) {
| ^^^^^^^^^ borrowed value does not live long enough
34 | let data_guard = data_lock.write().await;
35 | Some(f(&data_guard).await)
| -------------- argument requires that `map_guard` is borrowed for `'c`
...
39 | }
| - `map_guard` dropped here while still borrowed