По сути, ваша проблема может быть сведена к до следующего MCVE:
use std::sync::{Arc, Mutex};
struct Bar;
fn foo(_ : &Bar){
println!("foo called");
}
fn main(){
let example = Arc::new(Mutex::new(Bar));
std::thread::spawn(move ||{
let _ = example.clone();
});
// --- (1) ---
std::thread::spawn(move ||{
foo(&example.clone().lock().unwrap());
});
}
Теперь первая проблема в том, что example
перемещен. То есть, как только мы пересекли (1)
, оригинал example
считается перемещенным из. Вместо этого нам нужно сначала clone
и , затем move
:
let example = Arc::new(Mutex::new(Bar));
let local_state = example.clone();
std::thread::spawn(move ||{
let _ = local_state; // now fine!
});
Другая ошибка связана с недолговечным Arc
. По сути, он живет только для нас lock
на базовом Mutex
. Хотя мы знаем, что по крайней мере еще один Arc
указывает на память, компилятор не может этого доказать. Однако, если мы избавимся от clone()
, это нормально:
let local_state = example.clone();
std::thread::spawn(move ||{
foo(&local_state.lock().unwrap());
});
Однако вы также перебираете контейнер, потребляя его содержимое (clients
). Вместо этого используйте &
там, например, &local_state().unwrap().clients
).
Вы можете найти полный фиксированный код ниже или на детской площадке :
use std::sync::{Arc, Mutex};
struct Bar;
fn foo(_ : &Bar){
println!("foo called");
}
fn main(){
let example = Arc::new(Mutex::new(Bar));
let local_state = example.clone();
std::thread::spawn(move ||{
let _ = local_state;
});
let local_state = example.clone();
std::thread::spawn(move ||{
foo(&local_state.lock().unwrap());
}).join();
}