I want to write a program with 2 threads. The first one should update data and the second one should use it. The problem is both of the threads must use the same data. As I understand I can't use mutex in this case. I tried to write a program using static
and I did it well. But using static
is unsafe, so I decided to found a safe solution.
As I understand in my case it's better to use atomic values. So, I've created an array of atomic values. And the code is not working now, and I can't understand why
use std::{thread, time::{Duration}, sync::{Arc, atomic::{AtomicU16, Ordering}}};
use rdev::{Key, EventType};
fn main() {
let data = Arc::new([0_u16; 6].map(|it| AtomicU16::new(it)));
write(Arc::clone(&data));
listen(data);
}
fn write(data: Arc<[AtomicU16; 6]>) {
thread::spawn(move || {
loop {
let row = data.map(|it| it.load(Ordering::Relaxed).to_string()).join(";");
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// |
// cannot move out of here
// move occurs because value has type `[AtomicU16; 6]`, which does not implement the `Copy` trait
println!("{row}");
thread::sleep(Duration::from_secs(1));
}
});
}
Could you please explain me, how can I map these values?
CodePudding user response:
Do not use map
directly, which consumes the array, use an iterator instead (which yields references to the inner values), then map over the iterator:
use std::{
sync::{
atomic::{AtomicU16, Ordering},
Arc,
},
thread,
time::Duration,
};
fn main() {
let data = Arc::new([0_u16; 6].map(|it| AtomicU16::new(it)));
write(Arc::clone(&data));
}
fn write(data: Arc<[AtomicU16; 6]>) {
thread::spawn(move || loop {
let row = data
.iter()
.map(|it| it.load(Ordering::Relaxed).to_string())
.collect::<Vec<String>>()
.join(";");
println!("{row}");
thread::sleep(Duration::from_secs(1));
});
}