I have greatly simplified my specific problem to the example below:
struct MyStruct {
my_lock: RwLock<RwLock<u8>>
}
impl MyStruct {
async fn my_function(&self) -> RwLockReadGuard<u8> {
let outer_guard = self.my_lock.read().await;
let inner_guard = outer_guard.read().await;
return inner_guard;
}
}
I'm getting the following error:
error[E0515]: cannot return value referencing local variable `outer_guard`
--> src/geolocations/geocode/client.rs:99:10
|
98 | let inner_guard = outer_guard.read().await;
| ----------- `outer_guard` is borrowed here
99 | return inner_guard;
| ^^^^^^^^^^^ returns a value referencing data owned by the current function
In my mind, the lifetime of inner_guard
is bound to the lifetime of my_lock
which is bound to the lifetime of self
. Why does Rust care at all about the fact that outer_guard
is bound to the scope of the function with regards to returning inner_guard
if the two are not bound to each other?
How can I return the second RwLockReadGuard<u8>
from the function? Or at a minimum, a reference to the u8
value it's guarding?
Depending on whether you ever need a &mut
to the inner data, you can use one of these approaches:
RwLock<HashMap<String, Arc<MyData>>>
and return a cloned Arc<MyData>
. This does not allow &mut
access to the MyData
but you may not need this. If you only need to read from it or replace the value entirely (which you can do by writing a new Arc
to the map with just a write lock on the map), you can use this approach.RwLock<HashMap<String, Arc<RwLock<MyData>>>>
and return a cloned Arc<RwLock<MyData>>
. This offers the same capabilities as the other type, but allows writing at the expense of needing to lock to access the inner data.Both approaches provide a kind of "snapshot" capability where accessing an entry value does not require holding a lock on the map itself. In particular, when using the first approach, tasks that take an Arc
can use a consistent point-in-time view of the cached data that will not change, even if the map is updated with a new value.
You might also consider looking into the moka
crate, which provides implementations of both synchronous and asynchronous caching maps, both of which handle locking and eviction for you.