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 ... //
}
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
}
}