I have a static HashMap
mapping u32
"handles" onto (generic) objects called ObjectCache<T>
, which can, given a handle and an async closure taking a reference to the corresponding object, pick up the corresponding object and call the asynchronous closure with the object as the argument:
pub struct ObjectCache<T> {
pub store: HashMap<u32, T>,
}
impl<T> ObjectCache<T> {
pub fn new() -> ObjectCache<T> {
ObjectCache {
store: Default::default(),
}
}
pub async fn get<F, R, U>(&self, handle: u32, closure: F) -> Result<R, ()>
where
F: Fn(&T) -> U,
U: Future<Output=Result<R, ()>>
{
match self.store.get(&handle) {
Some(obj) => closure(obj).await,
None => Err(())
}
}
}
In it, I want to store an Agent
struct which can, as a part of its API, asynchronously process a request:
lazy_static! {
pub static ref AGENT_CACHE: ObjectCache<Agent> = ObjectCache::<Agent>::new();
}
pub struct Agent;
impl Agent {
pub async fn process(&self, request: &str) -> Result<u32, ()> {
info!("Processing {}", request);
sleep(Duration::from_secs(1)).await;
Ok(42)
}
...
}
For each function in Agent
s API, I want to have corresponding function which takes the same arguments + a handle. This function picks up an agent corresponding to the handle from AGENT_CACHE
and calls the function using the cache's get()
function:
async fn perform_action(request: &str, handle: u32) -> Result<u32, ()> {
AGENT_CACHE.get(handle, |agent: &Agent| agent.process(request)).await
}
The problem is, the above code does not compile. The error is
error: lifetime may not live long enough
--> src/main.rs:59:46
|
59 | OBJECT_CACHE.get(handle, |agent: &Agent| agent.process(request)).await
| - - ^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'2`
| | |
| | return type of closure `impl futures::Future` contains a lifetime `'2`
| let's call the lifetime of this reference `'1`
It seems that the compiler must make sure that the value referenced in the argument is valid at the moment the future is called, and hence it must live at least as long the future itself. In this case, the value in the cache may live as long as static
, but perhaps also be dropped while the future is pending (?).
Is there a way to constrain the lifetimes in such a way that the code is safe, compiles and doesn't get rid of the get()
function?