Estou tentando usar um sinalizador booleano para sinalizar que um thread deve sair. No entanto, atualmente meu código viola as regras do verificador de empréstimo. Eu entendo por que ele viola essas regras, no entanto, o que eu não sei é qual é o design mais apropriado e como isso pode corrigir o problema.
fn long_running(exit_flag: &bool) {
loop {
std::thread::sleep(std::time::Duration::from_secs(10));
if *exit_flag {
break;
}
}
}
fn main() {
let mut exit_flag = false;
std::thread::scope(
|scope| {
let handle = scope.spawn(
|| {
long_running(&exit_flag); # (1)
}
);
exit_flag = true; # (2)
// terminate the consumer poll loop
handle.join().expect("failed to join thread");
}
);
}
O problema envolve as linhas marcadas com # (1)
e # (2)
.
# (1)
: A referência aexit_flag
é emprestada# (2)
: Tentando mutar a variável subjacente enquanto a referência ainda está emprestada
Isso não é permitido devido às regras do verificador de empréstimos.
- Uma solução para o problema pode ser alocar o sinalizador em heap e usá-lo para compartilhar os dados entre os dois threads.
- Entretanto, a intenção de uso
std::thread::scope
era permitir o lançamento de um thread que tenha acesso a uma variável local da pilha do thread pai (principal).
a propósito, tive a ideia de fazer isso neste tópico
Isso não funciona porque
exit_flag
deve ser emprestado pelo fechamento do thread enquanto também está sendo mutado viaexit_flag = true;
. Em outras palavras, não há garantia de que o thread tenha parado de observarexit_flag
enquanto está sendo mutado (que na verdade é o ponto principal deexit_flag
).Você precisará de um
AtomicBool
para fazer isso:Observe que removi
handle.join()
, poisthread::scope
já garante que todos os threads foram unidos quando ele retornar.