3

I have a struct which roughly looks as follows

struct Node {
    id: Arc<i32>,
    data: Arc<Mutex<i32>>, // Actually not i32, but that is not important for this question.
    rx: Receiver<()>,
    tx: Sender<()>
}

I use Receiver and Sender from mpsc::channel.

I want to share this across multiple threads. I have one "user" thread in which the user of Node executes some functions on Node. This will cause some UDP messages being sent to other computers and this thread will block on rx.recv(). In the background I have one or more threads that perform a blocking receive call on UDP sockets. When they receive a message they update the data field of the Node struct and when a background thread notices that sufficiently many messages have been received, it will send () using tx.send(), to let the user-thread continue its execution.

To share a Node instance to another thread, I do something like this:

let node: Arc<Node> = ...
let node_for_background_thread = Arc::clone(&node);
let background_thread_handle = thread::spawn(move || {
    node_for_background_thread.start_receive_loop();
});

I need to access all fields of Node (e.g. id and data) in both the user thread and the background threads. That's why I want to share a single instance of Node across them. But neither Receiver nor Sender is Sync, so the above doesn't compile. I know I can clone Sender to put an owned one of them in each background thread.

One solution I see is to not include rx and tx in Node. But then I would lose encapsulation since then the creator of Node instances would have to create the channel and also spawn the background threads. I want to keep it all encapsulated in Node if possible.

The code snipper above is where I could manually clone the Sender. I don't need to clone the Receiver since I will only ever have one thread that will use it.

  • 1
    Are you using `std::mpsc`? `Sender` is `Clone`, you should give each thread their own clone of the sender. However the `sc` means Single Consumer, so you can't share the `Receiver` by design. The `crossbeam` crate provides MPMC channels similar to the ones in std. – mcarton Jul 08 '19 at 14:27
  • Thanks for your comment! I will update my questions to clarify a little. – arcus_mannen Jul 08 '19 at 14:30
  • You could wrap your `Receiver` into `Arc>` as well. – swizard Jul 09 '19 at 13:11
  • Does this answer your question? [Rust mpsc::Sender cannot be shared between threads?](https://stackoverflow.com/questions/40384274/rust-mpscsender-cannot-be-shared-between-threads) – Aunmag Dec 18 '20 at 09:52

1 Answers1

0

As I answered here: https://stackoverflow.com/a/65354846/6070255

You may use std::sync::mpsc::SyncSender from the standard library. The difference is that it implements the Sync trait but it will may block if there is no space in the internal buffer while sending a message.

For more information:

Aunmag
  • 852
  • 12
  • 17