I have a HashMap<&'static str, i32>
, I constructed it like this:
let mut to_spy_on: HashMap<&'static str, i32> = HashMap::new();
to_spy_on.insert("a", 1);
to_spy_on.insert("b", 2);
let to_spy_on_box = Arc::new(Mutex::new(to_spy_on));
The values from to_spy_on
is changing on an unpredictable interval frequecy. I simulate this kind of changing action like this:
fn change_data_on_background(data: &Arc<Mutex<HashMap<&'static str, i32>>>, key: &'static str) {
thread::spawn({
let to_spy_on_box = Arc::clone(&data);
move || {
let mut rng = thread_rng();
let range_for_v = UniformInt::<i32>::new_inclusive(1, 500);
let range_for_sleep = UniformInt::<u64>::new_inclusive(10, 300);
for i in 1 .. 100 {
let rand_v = range_for_v.sample(&mut rng);
let rand_time = range_for_sleep.sample(&mut rng);
*to_spy_on_box.lock().unwrap().get_mut(key).unwrap() = rand_v;
thread::sleep(Duration::from_millis(rand_time));
}
}
});
}
change_data_on_background(&to_spy_on_box, "a");
change_data_on_background(&to_spy_on_box, "b");
What I am trying to do is that as soon as the values from to_spy_on
changed, I print the new values.
I tried to realize that as following:
fn spy_on_data(data: &Arc<Mutex<HashMap<&'static str, i32>>>, key: &'static str) {
thread::spawn({
let to_spy_on_box = Arc::clone(&data);
move || {
let mut last_seen_data = to_spy_on_box.lock().unwrap()[key];
for i in 1 .. 10_000 {
let now_seen_data = to_spy_on_box.lock().unwrap()[key];
if !(last_seen_data == now_seen_data) {
println!("the value: {:?}, now changed to {:?}", key, now_seen_data);
last_seen_data = now_seen_data;
}
thread::sleep(Duration::from_millis(10));
}
}
});
}
spy_on_data(&to_spy_on_box, "a");
spy_on_data(&to_spy_on_box, "b");
This is the playground.
But the function spy_on_data
consume too much cpu resources, because it keep running the loop per 10ms although sometimes the update time interval is 300ms.
So is there a way I can avoid that. The mothod I can imaging is like:
fn spy_on_data_callback(data: &Arc<Mutex<HashMap<&'static str, i32>>>, key: &'static str) {
thread::spawn({
let to_spy_on_box = Arc::clone(&data);
move || {
loop {
is_the_data_changed? => data[key] {
println!(...)
}
}
}
});
}
How can I do it?