0

I am trying to store the state of my app which includes a list of traits that are initialized in the beginning and pass the state between multiple threads but I am getting an error.

use std::sync::{Arc, RwLock};
use std::thread;
use std::time::Duration;

trait TestTrait {
    fn test(&self);
}

struct MyTestStruct {}

impl TestTrait for MyTestStruct {
    fn test(&self) {
        println!("Test trait called");
    }
}

struct DataStore {
    t: Box<dyn TestTrait>,
}

fn main() {
    let s = Arc::new(RwLock::new(DataStore {
        t: Box::new(MyTestStruct {}),
    }));
    let s_clone = s.clone();
    thread::spawn(move || {
        for i in 1..10 {
            s_clone.read().unwrap().t.test();
            println!("hi number {} from the spawned thread!", i);
            thread::sleep(Duration::from_millis(1));
        }
    });

    for i in 1..5 {
        println!("hi number {} from the main thread!", i);
        thread::sleep(Duration::from_millis(1));
    }
}

When I run this, I get the following error:

error[E0277]: `(dyn TestTrait + 'static)` cannot be sent between threads safely
   --> src/main.rs:26:5
    |
26  |     thread::spawn(move || {
    |     ^^^^^^^^^^^^^ `(dyn TestTrait + 'static)` cannot be sent between threads safely
    |
    = help: the trait `std::marker::Send` is not implemented for `(dyn TestTrait + 'static)`
    = note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique<(dyn TestTrait + 'static)>`
    = note: required because it appears within the type `std::boxed::Box<(dyn TestTrait + 'static)>`
    = note: required because it appears within the type `DataStore`
    = note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::RwLock<DataStore>`
    = note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Arc<std::sync::RwLock<DataStore>>`
    = note: required because it appears within the type `[closure@src/main.rs:26:19: 32:6 s_clone:std::sync::Arc<std::sync::RwLock<DataStore>>]`

error[E0277]: `(dyn TestTrait + 'static)` cannot be shared between threads safely
   --> src/main.rs:26:5
    |
26  |     thread::spawn(move || {
    |     ^^^^^^^^^^^^^ `(dyn TestTrait + 'static)` cannot be shared between threads safely
    |
    = help: the trait `std::marker::Sync` is not implemented for `(dyn TestTrait + 'static)`
    = note: required because of the requirements on the impl of `std::marker::Sync` for `std::ptr::Unique<(dyn TestTrait + 'static)>`
    = note: required because it appears within the type `std::boxed::Box<(dyn TestTrait + 'static)>`
    = note: required because it appears within the type `DataStore`
    = note: required because of the requirements on the impl of `std::marker::Sync` for `std::sync::RwLock<DataStore>`
    = note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Arc<std::sync::RwLock<DataStore>>`
    = note: required because it appears within the type `[closure@src/main.rs:26:19: 32:6 s_clone:std::sync::Arc<std::sync::RwLock<DataStore>>]`

How do I fix this?

0

1 Answer 1

8

thread::spawn requires a closure that implements Send. Arc<T> only implements Send if T implements both Send and Sync.

Send and Sync are auto traits. You can add auto traits to a dyn Trait type to provide more information about the erased type:

struct DataStore {
    t: Box<dyn TestTrait + Send + Sync>,
}

If you are going to write dyn TestTrait + Send + Sync everywhere, then another option is to declare Send and Sync as supertraits of TestTrait:

trait TestTrait: Send + Sync {
    fn test(&self);
}
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.