Rust Arc / Mutex Попробуйте макрокоманду - PullRequest
0 голосов
/ 02 февраля 2019

Я пытаюсь выполнить несколько операций с переменной, общей для потоков, инкапсулированной в Arc<Mutex>.Поскольку не все операции могут быть успешными, я пытаюсь использовать макрос try! или оператор ? для автоматического распространения ошибок.

Вот минимальный жизнеспособный пример моего кода:

lazy_static! {
    static ref BIG_NUMBER: Arc<Mutex<Option<u32>>> = Arc::new(Mutex::new(Some(174)));
}

pub fn unpack_big_number() -> Result<u32, Box<Error>> {
    let big_number_arc = Arc::clone(&BIG_NUMBER);
    let mutex_guard_result = big_number_arc.lock();
    let guarded_big_number_option = mutex_guard_result?;
    let dereferenced_big_number_option = *guarded_big_number_option;
    let big_number = dereferenced_big_number_option.unwrap();

    // do some subsequent operations
    let result = big_number + 5;

    // happy path
    Ok(result)
}

Вы заметите, что в строке, где я объявляю guarded_big_number_option, у меня есть ? в конце.Эта строка выдает следующую ошибку компилятора (чего не происходит, когда я заменяю ? на .unwrap():

error[E0597]: `big_number_arc` does not live long enough
  --> src/main.rs:32:30
   |
 7 |     let mutex_guard_result = big_number_arc.lock();
   |                              ^^^^^^^^^^^^^^ borrowed value does not live long enough
...
17 | }
   | - borrowed value only lives until here
   |
   = note: borrowed value must be valid for the static lifetime...

Теперь дело в том, что я понимаю, что я не пытаюсьиспользуйте big_number_arc вне его срока действия. Я пытаюсь извлечь потенциал PoisonError, содержащийся в результате. Как я могу правильно извлечь эту ошибку и заставить это распространение работать?

Кроме того, если это поможет,Вот снимок экрана с аннотациями типов, которые моя среда IDE автоматически добавляет к каждой строке:

CLion screenshot of code snippet

1 Ответ

0 голосов
/ 02 февраля 2019

lock() функция возвращает LockResult<MutexGuard<T>>. Документация гласит следующее:

Обратите внимание, что вариант Err также несет связанный защитный элемент, и его можно получить с помощью метода into_inner

, поэтомувы по сути пытаетесь вернуть ссылку на локальную переменную (обернутую в PoisonError struct), что, очевидно, неверно.

Как это исправить?Вы можете преобразовать эту ошибку во что-либо без таких ссылок, например в String:

let guarded_big_number_option = mutex_guard_result.map_err(|e| e.to_string())?;
...