#rust
#Ржавчина
Вопрос:
Мне трудно понять, как решить эту проблему.
Итак, у меня есть класс ArcWorker
, содержащий общую ссылку на Worker (как вы можете заметить ниже).
Я написал функцию в ArcWorker
вызываемой join()
, в которой строка self.internal.lock().unwrap().join();
завершается ошибкой со следующей ошибкой:
не удается выйти из разыменования
std::sync::MutexGuard<'_, models::worker::Worker>
Что я пытаюсь через эту строку, так это заблокировать мьютекс, развернуть и вызвать join()
функцию из рабочего класса.
Насколько я понимаю, как только вызывается функция блокировки и она заимствует ссылку на self (amp;self), мне нужен какой-то способ передать self по значению в join (функция объединения std::thread требует передачи self по значению).
Что я могу сделать, чтобы это сработало? Пытался найти ответ на мой вопрос в течение нескольких часов, но безрезультатно.
pub struct Worker {
accounts: Vec<Arc<Mutex<Account>>>,
thread_join_handle: Option<thread::JoinHandle<()>>
}
pub struct ArcWorker {
internal: Arc<Mutex<Worker>>
}
impl ArcWorker {
pub fn new(accounts: Vec<Arc<Mutex<Account>>>) -> ArcWorker {
return ArcWorker {
internal: Arc::new(Mutex::new(Worker {
accounts: accounts,
thread_join_handle: None
}))
}
}
pub fn spawn(amp;self) {
let local_self_1 = self.internal.clone();
self.internal.lock().unwrap().thread_join_handle = Some(thread::spawn(move || {
println!("Spawn worker");
local_self_1.lock().unwrap().perform_random_transactions();
}));
}
pub fn join(amp;self) {
self.internal.lock().unwrap().join();
}
}
impl Worker {
fn join(self) {
if let Some(thread_join_handle) = self.thread_join_handle {
thread_join_handle.join().expect("Couldn't join the associated threads.")
}
}
fn perform_random_transactions(amp;self) {
}
}
Комментарии:
1. Поскольку вы уже
JoinHandle
используете anOption
, вы можете сделатьWorker::join()
takeamp;mut self
вместоself
и изменитьif let
наif let Some(thread_join_handle) = self.thread_join_handle.take()
(обратите внимание на добавленноеtake()
). ЗатемArcWorker::join()
следует скомпилировать как есть.2. Потрясающе, это было то, что мне нужно. Теперь это работает. Большое спасибо!
Ответ №1:
Поскольку у вас уже есть JoinHandle
опция, вы можете сделать Worker::join()
take amp;mut self
вместо self
и изменить if let
условие на:
// note added `.take()`
if let Some(thread_join_handle) = self.thread_join_handle.take() {
Option::take()
переместит дескриптор из опции и предоставит вам право собственности на нее, оставив None
при self.thread_join_handle
этом . С этим изменением ArcWorker::join()
следует скомпилировать как есть.