Hi, I'm pretty new to Rust.
Trying to build an event/callback mechanism on a closure with async block that captures an Arc
. Usually such an async block in tokio::spawn allows for a cloned Arc quite easily. But once I put it into a closure that captures and clones the Arc
, I am totally stuck. Can't yet reason about the issue.
Here is a simplified version of the code. The real code will have an event handler tokio task that listens to messages and calls a registered closure (passed across threads/tasks):
use std::sync::Arc;
use futures::Future;
use log::info;
async fn run_event_handler<Fut, Afn>(id: u32, handler: Afn)
where
Fut: Future<Output=()>,
Afn: Fn(String) -> Fut + Send + 'static
{
let handler_id = format!("Handler-{id}");
handler(handler_id).await;
}
#[tokio::main(flavor = "multi_thread")]
async fn main() {
env_logger::init();
let context = Arc::new("Some Context".to_string());
for i in 0..=10 {
run_event_handler(i, {
let context = context.clone();
|handler_id| async move {
info!("Context: {}, id: {}", &context, handler_id);
}
});
}
}
Compiler errors are as follows:
error[E0507]: cannot move out of `context`, a captured variable in an `Fn` closure
--> src/bin/test_async_closure.rs:22:37
|
21 | let context = context.clone();
| ------- captured outer variable
22 | |handler_id| async move { info!("Context: {}, id: {}", &context, handler_id) }
| ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-------^^^^^^^^^^^^^^^
| | | |
| | | variable moved due to use in generator
| | | move occurs because `context` has type `Arc<String>`, which does not implement the `Copy` trait
| | move out of `context` occurs here
| captured by this `Fn` closure
I tried many combinations including multiple clones, doing clones in different places. None bear fruits. A similar Arc
can move into a tokio::spawn without issues. Thanks for any pointers!