Как мне использовать Condvar без перемещения переменной Mutex? - PullRequest
0 голосов
/ 08 июля 2019

Я хочу использовать Condvar в моей программе.Ниже краткий тест этого.Я знаю, что он навсегда застрянет в цикле.

use std::sync::{Arc, Condvar, Mutex};

fn main() {
    let var_in_lock = Arc::new(Mutex::new(8));
    let cvar = Arc::new(Condvar::new());

    let unlocked = var_in_lock.lock().unwrap();

    loop {
        cvar.wait(unlocked).unwrap();
    }
}

Он не компилируется:

error[E0382]: use of moved value: `unlocked`
  --> src/main.rs:10:19
   |
7  |     let unlocked = var_in_lock.lock().unwrap();
   |         -------- move occurs because `unlocked` has type `std::sync::MutexGuard<'_, i32>`, which does not implement the `Copy` trait
...
10 |         cvar.wait(unlocked).unwrap();
   |                   ^^^^^^^^ value moved here, in previous iteration of loop

Я посмотрел на пример в Rustдокументация.Я заметил две разницы:

  1. Они создают Condvar и Mutex в паре.Это не должно иметь значения, верно?Я хочу создать их отдельно.
  2. Они соответствуют блокировке с помощью ключевого слова ref, что, если я правильно понимаю этот ответ, означает, что сделана ссылка на блокировку.Я подумал, что если изменить строку на cvar.wait(&unlocked).unwrap();, это будет то же самое, но потом компилятор пожалуется, что ожидается MutexGuard, а не ссылка.

Как я могу это сделатькомпилировать

1 Ответ

1 голос
/ 08 июля 2019

Разница в том, что вы не заметили, что wait возвращает MutexGuard:

pub fn wait<'a, T>(
    &self,
    guard: MutexGuard<'a, T>
) -> LockResult<MutexGuard<'a, T>>
while !*started {
    started = cvar.wait(started).unwrap();
}

wait становится владельцем MutexGuardпоскольку он снимает блокировку, а затем снова ее получает.Передача владения статически не позволяет использовать неправильно заблокированную (или разблокированную) переменную, пример использования системы типов Rust для преимущества программистов.


Вам необходимо сделать то же самое в своем коде:

let mut unlocked = var_in_lock.lock().unwrap();

loop {
    unlocked = cvar.wait(unlocked).unwrap();
}

См. Также:

...