Cell<T>

Consider this program, where we have a requirement to mutate bag with two mutable references to it:

// without_cell.rs

use std::cell::Cell;

#[derive(Debug)]
struct Bag {
item: Box<u32>
}

fn main() {
let mut bag = Cell::new(Bag { item: Box::new(1) });
let hand1 = &mut bag;
let hand2 = &mut bag;
*hand1 = Cell::new(Bag {item: Box::new(2)});
*hand2 = Cell::new(Bag {item: Box::new(2)});
}

But, of course, this does not compile due to the borrow checking rules:

We can make this work by encapsulating the bag value inside a Cell. Our code is updated as follows:

// cell.rs

use std::cell::Cell;

#[derive(Debug)]
struct Bag {
item: Box<u32>
}

fn main() {
let bag = Cell::new(Bag { item: Box::new(1) });
let hand1 = &bag;
let hand2 = &bag;
hand1.set(Bag { item: Box::new(2)});
hand2.set(Bag { item: Box::new(3)});
}

This works as you would expect, and the only added cost is that you have to write a bit more. The additional runtime cost is zero, though, and the references to the mutable things remain immutable.

The Cell<T> type is a smart pointer type that enables mutability for values, even behind an immutable reference. It provides this capability with very minimal overhead and has a minimal API:

  • Cell::new method allows you to create new instances of the Cell type by passing it any type T.
  • get: The get method allows you to copy of the value in the cell. This method is only available if the wrapped type T is Copy.
  • set: Allows you to modify the inner value, even behind a immutable reference.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset