Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Moving Receiver to thread complains about Sync, but expected Send

I'm trying to reference, via an Arc, a receiver into a thread, so I can do centralized pub-sub via dispatcher. However, I get the following error:

src/dispatcher.rs:58:11: 58:24 error: the trait `core::marker::Sync` is not implemented for the type `core::cell::UnsafeCell<std::sync::mpsc::Flavor<dispatcher::DispatchMessage>>` [E0277]
src/dispatcher.rs:58           thread::spawn(move || {
                               ^~~~~~~~~~~~~
src/dispatcher.rs:58:11: 58:24 note: `core::cell::UnsafeCell<std::sync::mpsc::Flavor<dispatcher::DispatchMessage>>` cannot be shared between threads safely
src/dispatcher.rs:58           thread::spawn(move || {

Wat! I thought only Send was required for moving across channels? The code of DispatchMessage is:

#[derive(PartialEq, Debug, Clone)]
enum DispatchType {
    ChangeCurrentChannel,
    OutgoingMessage,
    IncomingMessage
}

#[derive(Clone)]
struct DispatchMessage {
   dispatch_type: DispatchType,
   payload: String
}

Both String and surely Enum are Send, right? Why is it complaining about Sync?

The relevant part from the dispatcher:

pub fn start(&self) {
   let shared_subscribers = Arc::new(self.subscribers);
   for ref broadcaster in &self.broadcasters {
      let shared_broadcaster = Arc::new(Mutex::new(broadcaster));

      let broadcaster = shared_broadcaster.clone();
      let subscribers = shared_subscribers.clone();
      thread::spawn(move || {
         loop {
            let message = &broadcaster.lock().unwrap().recv().ok().expect("Couldn't receive message in broadcaster");
            match subscribers.get(type_to_str(&message.dispatch_type)) {
              Some(ref subs) => { 
                  for sub in subs.iter() { sub.send(*message).unwrap(); }
              },
              None => ()
            }

         }
      });
   }
}

Full dispatcher code is in this gist: https://gist.github.com/timonv/5cdc56bf671cee69d3fa

If it's still relevant, built against the 5-2-2015 nightly.

like image 559
Timon Vonk Avatar asked May 06 '15 20:05

Timon Vonk


1 Answers

Arc requires Sync, and it seems to me like you're attempting to put channels inside an Arc. Channels are not Sync, neither Sender nor Receiver.

Without knowing what you're trying to do, here are some things that may help you:

  • it's possible to clone Sender, so where you would probably Arc a T and share it between many threads, you can instead clone a Sender and send it to many threads, since it is Send
  • otherwise (and especially for Receiver, which you can't clone) you have to stick it inside an Arc<Mutex<T>>, which makes it Sync.
like image 72
Jorge Israel Peña Avatar answered Sep 19 '22 15:09

Jorge Israel Peña