Using thread loop inside a struct

One of the things that Rust promises to protect you against is data races, namely, when data is being modified from one thread in parallel with another thread using that data. That's pretty much exactly what you are trying to do here.

One way to do this is to use a Mutex. A Mutex works by introducing a lock method for accessing your data. Whenever you call lock, the mutex will wait until nobody else is accessing the data, and then give you exclusive access to the data. Once the lock goes out of scope, the lock is released and some other call to lock will be given access, if any. That looks like this:

use std::collections::VecDeque;
use std::sync::{Arc, Mutex};
use std::thread;

#[derive(Clone)]
struct AbcStruct {
    data: Arc<Mutex<VecDeque<String>>>,
}

impl AbcStruct {
    fn new() -> AbcStruct {
        AbcStruct {
            data: Arc::new(Mutex::new(VecDeque::new()))
        }
    }
    
    fn append(&self, new_data: String) {
        let mut lock = self.data.lock().unwrap();
        lock.push_front(new_data);
    }
    
    fn start_thread(&self) {
        let me = self.clone();
        thread::spawn(move || me.print_data());
    }
    
    fn print_data(&self) {
        loop {
            let lock = self.data.lock().unwrap();
            println!("{:?}", &*lock);
        }
    }
}

fn main() {
    let abc = AbcStruct::new();
    abc.start_thread();

    for i in 0..1000 {
        abc.append(format!("{}", i));
    }
}

You can try it out here

Note that the above code also uses an Arc to share the data. The way an Arc works is that every time you clone it, you get a new shared handle to the same inner object. The shared object is destroyed when the last clone of the Arc is. This is really useful for sharing between multiple threads.

Note that in the above snippet, the background thread is killed when main returns.

1 Like