Sending type that doesn't implement Send

pub struct MyType {
    current_path: Rc<RefCell<String>>,
}

fn send_between(ms: Arc<Mutex<MyType>>) {
    std::thread::spawn(|| {
        println!("ms.path {:?}", ms.lock().unwrap().current_path);
    });
}

The error I'm getting:

error[E0277]: Rc<RefCell<String>> cannot be sent between threads safely
--> src/main.rs:10:5
|
10 | std :: thread::spawn(|| {
| ^^^^^^^^^^^^^^^^^^ Rc<RefCell<String>> cannot be sent between threads safely
|
= help: within MyType, the trait Send is not implemented for Rc<RefCell<String>>

I do understand what the error is trying to tell me, but I was convinced that if I use Arc<Mutex< around my type then I can send my type between threads. Isn't that the purpose of using Arc and Mutex?

The Rc type can never cross a thread boundary under any circumstances. An Arc or Mutex cannot change that.

The purpose of an Arc is to share a single value so that multiple threads can access it at the same time (normally only immutably). The purpose of a Mutex is to allow a shared value to be modified.

In general, a Mutex can only help you if a type is Send but not Sync. If the type isn't Send, then you're out of luck.

Hi and thanks for the answer.
But that is somewhat counter-intuitive. I can understand that Rc cannot cross thread boundary, but what about Mutex guarding it? Surely that guarantees that the access is synchronized?

No. The Rc type is not Send because its counter is shared between all clones of the Rc without synchronization. If you could send an Rc to a new thread in any way, then that counter could be accessed by multiple threads without synchronization by having the two threads access two different clones of the same Rc.

Your Mutex is only protecting one of the clones. The other clones are not protected by the mutex.

That makes perfect sense. Thank you.

So what is the solution to be able to send a type to different threads? Wrap each of its fields in Arc<Mutex<>>?

You only need the Arc/Mutex if the value needs to be shared between several threads. If you just need to move it, you can simply do that without using an Arc or a Mutex at all.

Additionally, you only need the Mutex if the shared value needs to mutable. If you just need an immutable shared value, an Arc alone is enough.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.