0

My problem basically is that in my program I need to pass around the reference to the s struct to multiple places including a new thread. In C I could for example declare it a a global struct and use it that way. How can I do this in rust?

I also need to use a RefCell wrapped in Rc for some code (my previous question).

fn a_thread(s: &SomeStruct) {

//... code using s reference ... //

}

struct SomeStruct {
    val: bool,
}

fn main() {
    let mut s = SomeStruct { val: true };

    let s_rc = Rc::new(RefCell::new(s));
    thread::spawn(move || a_thread(&s)); // <= error: use of moved value 's'
    
    
    //... code using the s_rc ... //
    

}



Andrzej C
  • 25
  • 5

1 Answers1

2

If one thread modifies the data and another reads it, that has to be synchronized, otherwise you have a data race. Safe Rust prevents data races through static analysis, so it won't allow you to get a &SomeStruct while the underlying values could be modified by another thread.

What you can do is use a mutex instead of RefCell, and Arc instead of Rc:

fn a_thread(s: Arc<Mutex<SomeStruct>) {
    // when you need data from s:
    {
        let s = s.lock().unwrap();
        // here you can read from s, or even obtain a `&SomeStruct`
        // but as long as you hold on to it, the main thread will be
        // blocked in its attempts to modify s
    }
}

fn main() {
    // create s on the heap
    let s = Arc::new(Mutex::new(SomeStruct { val: true }));

    // cloning the Arc creates another reference to the value
    let s2 = Arc::clone(&s);
    thread::spawn(move || a_thread(s2));
    
    //... code using s ... //
    {
        let s = s.lock().unwrap();
        // here you can modify s, but reading will be blocked
    }
}
user4815162342
  • 141,790
  • 18
  • 296
  • 355
  • Wouldn’t a RwLock work better here since only one thread needs to modify values? – RedBorg Nov 29 '20 at 13:23
  • 1
    @RedBorg It would work the same because the reader and the writer would still lock each other out. Last time I measured, acquiring an uncontended `RwLock` is more expensive than acquiring a `Mutex` because of its more complex bookkeeping. A `RwLock` should be used when it actually provides benefits: when there are multiple readers that would lock each other out if the data were behind a `Mutex`. – user4815162342 Nov 29 '20 at 13:48
  • @user4815162342 Of course, for a single thread, it would be more expensive. I thought there would be multiple threads all watching the same value, my bad. – RedBorg Nov 29 '20 at 14:41