I am playing with Rust\'s concurrency and trying to wrap my head around Send
/Sync
/Arc
/Mutex
. I have problems with sharing
Remember that types of original values which are converted to trait objects are erased. Therefore, the compiler can't know whether the data inside the Arc
is Send
and Sync
, and without these traits sharing data across threads may be unsafe. You need to specify that types which can be stored in Arc
must be Send
and Sync
:
let mut map: HashMap> = HashMap::new();
(try it here)
The Send
bound is required by thread::spawn()
, and Sync
is required by Arc
for it to be Send
. Additionally, thread::spawn()
also requires 'static
but it is implicit in this particular Arc
type declaration.
Of course, you will be able to store only Sync
and Send
implementations of Foo
, but this is necessary to ensure memory safety. However, in Rust synchronization is implemented with wrappers like Mutex
or RwLock
. They don't implement Foo
even if T
implements Foo
, therefore you won't be able to store, say, Mutex
inside your map (unless Foo
is your trait and you implemented it for Mutex
, which could be unwieldy), which would be necessary if your Foo
implementations are not Sync
but Send
(though I'm not sure I can provide an example of such type now).
To solve this you'd need to change map type to contain a mutex inside it explicitly:
let mut map: HashMap>> = HashMap::new();
This way, there is no need for the Sync
bound because Mutex
is Sync
if its contents are Send
.
And naturally, you won't be able to share Foo
implementations which are not Send
at all, and there is no way around it. This can happen, for example, if Foo
's implementation contains Rc
s.