1

I looked at this post but couldn't figure out where I was going wrong with my code. I have a vector of structs that each contain an mpsc::Sender and mpsc::Receiver and I'm trying to move each of these structs into a thread and keep getting this compile error (and a symmetrical one for the Sender). Since the Sender and Receiver are part of a struct, I wasn't sure how to clone them.

for obj in objs.iter() {
  let handle = thread::spawn(move || {
               ^^^^^^^^^^^^^ `std::sync::mpsc::Receiver<abc::xyz>` cannot be shared between threads safely
    obj.do_something();
    ...
  });
  ...
}
  • 1
    Here is a recommendation that will save you a lot of time: switch to [crossbeam-channel](https://crates.io/crates/crossbeam-channel), whose sender and receiver are both `Send` and `Sync`. (They're also more efficient and have a better-thought-out API.) – user4815162342 Apr 14 '21 at 18:32

1 Answers1

3

for obj in objs.iter() {

This means obj is an &T. The move closure means the reference gets moved into the closure but… that's it. It's a reference. Meaning the type being referenced must be Sync (and also you'll have lifetime issues because stdlib threads are not scoped, so the compiler will eventually tell you that the references don't live long enough).

If objs is a vector, removing the .iter() will fix that issue though it may trigger new ones: it'll perform an "owned" iteration, so you will be moving the obj itself into the loop.

If objs is not a vector, then make it a vector somehow because a slice can't hand out owned objects. Or clone everything but I rather doubt that's what you want. Your final option is to put every obj inside an Arc, and probably a Mutex/RwLock if you want to mutate them.

Masklinn
  • 34,759
  • 3
  • 38
  • 57