I am playing with Rust\'s concurrency and trying to wrap my head around Send/Sync/Arc/Mutex. I have problems with sharing
Vladimir gives one solution to your problem in the first half of his answer: tell Rust that your HashMap contains Foos which are Send and Sync. Alternatively, you may change the definition of Foo itself to include these trait bounds:
trait Foo: Sync + Send {
fn get_foo(&self) -> u8;
}
Since struct A is indeed Send and Sync, and since struct A does indeed implement trait Foo, the type checker will not complain when you use an Arc as an Arc.
If instead of sharing immutable (atomically reference counted) references to Foos you wanted to share mutable (atomically reference counted) references to Foos, you need to control access to the Foos. This can be accomplished using e.g. a Mutex. Since the Mutex would then be taking care of the synchronization, the Sync bound on Foo can be dropped. For example:
use std::{
collections::HashMap,
sync::{Arc, Mutex},
thread,
time::Duration,
};
#[derive(Debug)]
struct A {
foo: u8,
}
trait Foo: Send {
fn get_foo(&self) -> u8;
}
impl Foo for A {
fn get_foo(&self) -> u8 {
self.foo
}
}
fn main() {
let a = Arc::new(Mutex::new(A { foo: 8 }));
let mut map: HashMap>> = HashMap::new();
map.insert(8u8, a);
for _ in 0..2 {
let a = map.get(&8u8).expect("boom").clone();
thread::spawn(move || {
let result = a.lock().ok().expect("boom indeed").get_foo();
println!("Result: {}", result);
});
}
thread::sleep(Duration::from_millis(200));
}
(playground)