i need to have a thread that recursively checks a variable while the main thread changes the variable. however, it appears that with move
, the variable is not being changes by the lambda in register
. (i checked and the function works, its just that move
makes it so i cannot change the original variable)
the code i currently have created:
use std::io::stdin;
use std::thread;
use enigo::{self, Enigo, MouseControllable};
use enigo::MouseButton;
use livesplit_hotkey::*;
fn main() {
let mut input = String::new();
let mut started = false;
println!("How many clicks per tick? (too many will lag)");
stdin().read_line(&mut input).expect("Unable to read line");
let input2 = input.trim().parse::<u16>().unwrap();
for _ in 0 .. input2 {
thread::spawn(move || {
let mut enigo = Enigo::new();
loop {
if started {
println!("clicking"); // debug
enigo.mouse_click(MouseButton::Left);
}
}
});
}
println!("Press f8 to toggle clicking");
let hook = Hook::new().unwrap();
hook.register(Hotkey { key_code: KeyCode::F8, modifiers: Modifiers::empty() }, move || {
started = !started;
}).expect("Unable to assign hotkey");
loop {}
}
i know that there are things such as Arc and Mutex, but i'm unsure how to use them correctly.
CodePudding user response:
Just use a static AtomicBool
in place of started
:
use std::io::stdin;
use std::thread;
use enigo::{self, Enigo, MouseControllable};
use enigo::MouseButton;
use livesplit_hotkey::*;
static STARTED: atomic::AtomicBool = atomic::AtomicBool::new(false);
fn main() {
let mut input = String::new();
println!("How many clicks per tick? (too many will lag)");
stdin().read_line(&mut input).expect("Unable to read line");
let input2 = input.trim().parse::<u16>().unwrap();
for _ in 0 .. input2 {
thread::spawn(move || {
let mut enigo = Enigo::new();
loop {
if STARTED.load(atomic::Ordering::SeqCst) {
println!("clicking"); // debug
enigo.mouse_click(MouseButton::Left);
}
}
});
}
println!("Press f8 to toggle clicking");
let hook = Hook::new().unwrap();
hook.register(Hotkey { key_code: KeyCode::F8, modifiers: Modifiers::empty() }, move || {
// use xor(true) to emulate "NOT" operation
// true ^ true -> false
// false ^ true -> true
STARTED.fetch_xor(true, atomic::Ordering::SeqCst);
}).expect("Unable to assign hotkey");
loop {}
}
Note: Ordering::SeqCst
may not be the ideal atomic ordering for this. You could use one of the less strict orderings, but I'll leave that to you.