Hello community,
Is it possible to share a mutable object reference between two closures (each one being a different thread)?
I have an application that requires multiple producers (that will be indefinitely producing data) and a consumer that runs in parallel and I cannot share the data buffer between the threads. Any help is appreciated.
use tokio::task;
use std::{thread, time};
use std::sync::{Arc, Mutex};
struct Data {
value: i32
}
fn produce(data: &mut Arc<Mutex<Data>>) {
for i in 0..300 {
{
let mut data = data.lock().expect("Could not lock mutex");
data.value += 1;
println!("Produced: {}", data.value);
}
thread::sleep(time::Duration::from_millis(500));
}
}
fn consume(data: &mut Arc<Mutex<Data>>) {
for i in 0..300 {
{
let mut data = data.lock().expect("Could not lock mutex");
if data.value > 0 {
data.value -= 1;
println!("Consumed: {}", data.value);
}
}
thread::sleep(time::Duration::from_millis(1000));
}
}
#[tokio::main]
async fn main() {
let mut data = Arc::new(Mutex::new(Data{value: 0}));
let producing = task::spawn_blocking(move ||produce(&mut data));
let consuming = task::spawn_blocking(move ||consume(&mut data));
}
This code does not compile with the following error:
error[E0382]: use of moved value: `data`
--> future\./future.rs:39:42
|
37 | let mut data = Arc::new(Mutex::new(Data{value: 0}));
| -------- move occurs because `data` has type `Arc<std::sync::Mutex<Data>>`, which does not implement the `Copy` trait
38 | let producing = task::spawn_blocking(move ||produce(&mut data));
| ------- ---- variable moved due to use in closure
| |
| value moved into closure here
39 | let consuming = task::spawn_blocking(move ||consume(&mut data));
| ^^^^^^^ ---- use occurs due to use in closure
| |
| value used here after move