Run object function in different threads

I want to build an object and call its member function from different threads:

use std::sync::Arc;
use std::thread;
use std::time::Duration;
use std::sync::atomic::{AtomicBool, Ordering};

struct LogRecorder {
    run: AtomicBool,
}

impl LogRecorder {
    pub fn new() -> Self {
        LogRecorder {
            run: AtomicBool::new(false),
        }
    }

    pub fn start(&self) {
        self.run.store(true, Ordering::Relaxed);
    }

    pub fn stop(&self) {
        self.run.store(false, Ordering::Relaxed);
    }

    pub fn recording_loop(&self, channel: &str) {
        // Initialize
        while self.run.load(Ordering::Relaxed) {
            // Do Something with the channel
            println!("Recording {}...", channel);
        }
        println!("Stopped recording for {}", channel);
    }
}

fn main() {
    // Assuming utils::CHANNELS_NAMES defined somewhere
    let log_recorder = Arc::new(LogRecorder::new());

    log_recorder.start();

    let children: Vec<_> = utils::CHANNELS_NAMES.iter().map(|channel| {
        let log_recorder_clone = log_recorder.clone();
        thread::spawn(move || {
            log_recorder_clone.recording_loop(channel);
        })
    }).collect();

    thread::sleep(Duration::from_secs(10));

    log_recorder.stop();

    for child in children {
        let _ = child.join();
    }
}

I get this error.

error[E0596]: cannot borrow data in an `Arc` as mutable
  --> src/main.rs:92:13
   |
92 |             log_recorder_clone.recording_loop(channel);
   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable
   |
   = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Arc<LogRecorder>`

I tried to make the variables mutable to add mutex but still got an error.
How can I share object function between threads?

1 Like

Your example runs fine on the playground.

4 Likes

You are right
I guess that in this simple example the bug was fixed :sweat_smile:

Thanks for the check

Thanks,
Didn't knew this one.
Rust is still new to me so I'm finding my ways around with the borrowing and the macros.

So what you suggested is the better way?
Is it better by design / performance / convention?

Also, why did you remove the mutex member and called it as a static?

I don't think what benefit any sort of macro would have here. If you merely want to spawn threads, use std::thread::spawn() or std::thread::scope(). For sharing mutable data, use Arc<Mutex<_>>. No need to overcomplicate things.

If you show us an example that actually fails to compile and/or achieve what you want, we can make more useful, specific suggestions.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.