Hi, I would love to pass a Fn
closure to a function which runs repeatedly in tokio::spawn
. The closure will read a shared value, which could be modified in other threads, usgng tokio::sync::RwLock
.
When I wrote such a program, the compiler said the following error message. In this message, rw
is a RwLock
.
closure is `FnOnce` because it moves the variable `rw` out of its environment
I wrote the following code as a minimum sample (playground code is here).
use std::sync::Arc;
use tokio::sync::RwLock;
use futures::Future;
async fn test_spawn<R>(f: impl Fn() -> R)
where
R: Future<Output = ()>,
{
loop {
tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
f();
}
}
async fn test() {
let rw = Arc::new(RwLock::new(42));
let f = move || async move {
let v = rw.read().await;
println!("{}", *v);
};
let t = tokio::spawn(test_spawn(f));
let (r,) = tokio::join!(t);
r.unwrap();
}
I have tried the same thing without closure, and this works fine.
use std::sync::Arc;
use tokio::sync::RwLock;
use futures::Future;
async fn test_spawn(rw: Arc<RwLock<i32>>)
{
loop {
tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
let v = rw.read().await;
println!("{}", *v);
}
}
async fn test() {
let rw = Arc::new(RwLock::new(42));
let t = tokio::spawn(test_spawn(rw));
let (r,) = tokio::join!(t);
r.unwrap();
}
How should I change the code to compile successfully? I would appreciate if you have any advice.
Thanks!