Calling a function that takes reference to RwLockGuard using Fn object

49 Views Asked by At

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
0

There are 0 best solutions below