Home > OS >  How to map atomic values in array in Rust
How to map atomic values in array in Rust

Time:07-11

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));
    });
}

Playground

  • Related