Este código é concluído imediatamente ( playground ):
use std::sync::Mutex;
fn f(_: usize, _: usize) {}
fn main() {
let m = Mutex::new(0);
let i = { *m.lock().unwrap() };
let j = { *m.lock().unwrap() };
f(i, j);
}
Este código também é concluído imediatamente ( playground ):
use std::sync::Mutex;
fn f(_: usize, _: usize) {}
fn main() {
let m = Mutex::new(0);
f(
{
let i = *m.lock().unwrap();
i
},
{
let j = *m.lock().unwrap();
j
},
);
}
Este código, que eu acho que é semanticamente o mesmo que os códigos acima, bloqueia para sempre ( playground ):
use std::sync::Mutex;
fn f(_: usize, _: usize) {}
fn main() {
let m = Mutex::new(0);
f({ *m.lock().unwrap() }, { *m.lock().unwrap() });
}
Por que?
Isso acontece devido a escopos temporários .
No terceiro exemplo, o menor escopo que se aplica à proteção de correspondência temporária é a instrução inteira que contém a chamada para
f
. (Observe que a expressão final em um bloco não é uma instrução. )Portanto, seus segundo e terceiro exemplos de código não são semanticamente os mesmos. No terceiro exemplo, os tempos de vida dos mutex guards criados nas expressões de bloco são estendidos para toda a declaração where
f
é chamado, mas no segundo exemplo, os tempos de vida dos mutex guards são limitados àslet
declarações dentro da expressão de bloco correspondente.