I have this code:
let mut is_ok_test = false;
let handle = thread::spawn(move || {
is_ok_test = true;
});
handle.join().unwrap();
if is_ok_test == true { println!("Success"); } else { println!("Test Failed") }
The is_ok_test
variable always remains false. I don't understand why.
When modifying the variable inside I get a warning like this:
value assigned to `is_ok_test` is never read
maybe it is overwritten before being read?
unused variable: `is_ok_test`
did you mean to capture by reference instead?
I tried to add &
but it doesn't work.
CodePudding user response:
The answer from @cafce25 is correct, but another way is to use scoped thread, since you join the thread before checking is_ok_test
:
let mut is_ok_test = false;
thread::scope(|s| {
s.spawn(|| {
is_ok_test = true;
});
});
if is_ok_test == true {
println!("Success");
} else {
println!("Test Failed")
}
Scoped threads can capture variables from the outer function (notice there is no move
).
CodePudding user response:
The problem is that due to move || {...
and booleans being Copy
instead of changing the outside boolean you create a copy of it inside the closure.
That's also what your warnings are referring to, the inner is_ok
is never read.
You can share ownership between the new and the main thread by using an Arc
. To get back mutability you can use an AtomicBool
:
use std::sync::Arc;
use std::sync::atomic::AtomicBool;
use std::sync::atomic::Ordering::Relaxed;
fn main() {
let mut is_ok_test = Arc::new(AtomicBool::new(false));
let handle = {
let is_ok_test = is_ok_test.clone();
std::thread::spawn(move || {
is_ok_test.store(true, Relaxed);
})
};
handle.join().unwrap();
if is_ok_test.load(Relaxed) == true { println!("Success"); } else { eprintln!("Test Failed") }
}