Mutabilidade Interior

Em algumas situaçÔes, Ă© necessĂĄrio modificar dados atrĂĄs de uma referĂȘncia compartilhada (somente leitura). Por exemplo, uma estrutura de dados compartilhada pode ter um cache interno e desejar atualizar esse cache a partir de mĂ©todos somente leitura.

O padrĂŁo de "mutabilidade interna" permite acesso exclusivo (mutĂĄvel) por trĂĄs de uma referĂȘncia compartilhada. A biblioteca padrĂŁo fornece vĂĄrias maneiras de fazer isso, garantindo segurança, geralmente realizando uma verificação em tempo de execução.

RefCell

use std::cell::RefCell;

fn main() {
    // Observe que `cell` NÃO é declarado como mutåvel.
    let cell = RefCell::new(5);

    {
        let mut cell_ref = cell.borrow_mut();
        *cell_ref = 123;

        // Isso gera um erro em tempo de execução.
        // let other = cell.borrow();
        // println!("{}", *other);
    }

    println!("{cell:?}");
}

Cell

Cell envolve um valor e permite obter ou definir o valor, mesmo com uma referĂȘncia compartilhada para o Cell. No entanto, nĂŁo permite nenhuma referĂȘncia ao valor. Como nĂŁo hĂĄ referĂȘncias, as regras de emprĂ©stimo nĂŁo podem ser quebradas.

use std::cell::Cell;

fn main() {
    // Observe que `cell` NÃO é declarado como mutåvel.
    let cell = Cell::new(5);

    cell.set(123);
    println!("{}", cell.get());
}
This slide should take about 10 minutes.

O principal a ser observado neste slide Ă© que o Rust fornece maneiras seguras de modificar dados por trĂĄs de uma referĂȘncia compartilhada. HĂĄ uma variedade de maneiras de garantir essa segurança, e RefCell e Cell sĂŁo duas delas.

  • RefCell faz cumprir as regras de emprĂ©stimo usuais do Rust (ou vĂĄrias referĂȘncias compartilhadas ou uma Ășnica referĂȘncia exclusiva) com uma verificação em tempo de execução. Neste caso, todos os emprĂ©stimos sĂŁo muito curtos e nunca se sobrepĂ”em, entĂŁo as verificaçÔes sempre tĂȘm sucesso.

    • O bloco extra no exemplo de RefCell Ă© para encerrar o emprĂ©stimo criado pela chamada a borrow_mut antes de imprimir o cell. Tentar imprimir um RefCell emprestado mostra apenas a mensagem "{borrowed}".
  • Cell Ă© um meio mais simples de garantir a segurança: ele tem um mĂ©todo set que recebe &self. Isso nĂŁo precisa de uma verificação em tempo de execução, mas requer mover valores, o que pode ter seu prĂłprio custo.

  • Tanto RefCell quanto Cell sĂŁo !Sync, o que significa que &RefCell e &Cell nĂŁo podem ser passados entre threads. Isso impede que duas threads tentem acessar o cell ao mesmo tempo.