I'd like to share a struct with an Arc<Mutex<Fn(i64)>>
through a thread. I've minimally reproduced the problem below:
use std::sync::{Arc, Mutex};
struct NonSendable {
problematic: Arc<Mutex<Fn(i64)>>,
}
fn main() {
let bad = NonSendable {
problematic: Arc::new(Mutex::new(|i| println!("{}", i))),
};
std::thread::spawn(|| {
for i in 0..10 {
let f = bad.problematic.lock().unwrap();
f(i);
}
});
}
However, this errors on compilation.
error[E0277]: `(dyn std::ops::Fn(i64) + 'static)` cannot be sent between threads safely
--> src/main.rs:13:5
|
13 | std::thread::spawn(|| {
| ^^^^^^^^^^^^^^^^^^ `(dyn std::ops::Fn(i64) + 'static)` cannot be sent between threads safely
|
= help: the trait `std::marker::Send` is not implemented for `(dyn std::ops::Fn(i64) + 'static)`
= note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Mutex<(dyn std::ops::Fn(i64) + 'static)
>`
= note: required because of the requirements on the impl of `std::marker::Sync` for `std::sync::Arc<std::sync::Mutex<(dyn std::ops::Fn(
i64) + 'static)>>`
= note: required because it appears within the type `NonSendable`
= note: required because of the requirements on the impl of `std::marker::Send` for `&NonSendable`
= note: required because it appears within the type `[closure@src/main.rs:13:24: 18:6 bad:&NonSendable]`
= note: required by `std::thread::spawn`
error: aborting due to previous error
I guess I might understand why a Fn
isn't Send
or Sync
, but should a Mutex
not cover that issue? I've also tried to Box
the Fn
and use FnMut
instead.
The end goal here is to have a Vec
of closures that can be accessed and modified in one thread while read in another thread, so I think I need multiple non-mut
references (or maybe an Arc
) to coexist in different threads with an Arc<Mutex<Vec<Fn>>>
or similar as a member, but if I can't get the above to work I'll have to use a different strategy.