mirror of
https://github.com/google/comprehensive-rust.git
synced 2025-02-09 12:13:52 +02:00
Improve interior mutability slide (#1683)
Mutex is probably more broadly understood by people coming from other languages. Fixes #1512.
This commit is contained in:
parent
d731da4a5e
commit
73068d2af2
@ -2,26 +2,17 @@
|
||||
minutes: 10
|
||||
---
|
||||
|
||||
<!-- NOTES:
|
||||
Introduce the concept, with an example based on Mutex showing an `&self` method doing mutation; reference Cell/RefCell without detail.
|
||||
-->
|
||||
|
||||
# Interior Mutability
|
||||
|
||||
Rust provides a few safe means of modifying a value given only a shared
|
||||
reference to that value. All of these replace compile-time checks with runtime
|
||||
checks.
|
||||
In some situations, it's necessary to modify data behind a shared (read-only)
|
||||
reference. For example, a shared data structure might have an internal cache,
|
||||
and wish to update that cache from read-only methods.
|
||||
|
||||
## `Cell` and `RefCell`
|
||||
The "interior mutability" pattern allows exclusive (mutable) access behind a
|
||||
shared reference. The standard library provides several ways to do this, all
|
||||
while still ensuring safety, typically by performing a runtime check.
|
||||
|
||||
[`Cell`](https://doc.rust-lang.org/std/cell/struct.Cell.html) and
|
||||
[`RefCell`](https://doc.rust-lang.org/std/cell/struct.RefCell.html) implement
|
||||
what Rust calls _interior mutability:_ mutation of values in an immutable
|
||||
context.
|
||||
|
||||
`Cell` is typically used for simple types, as it requires copying or moving
|
||||
values. More complex interior types typically use `RefCell`, which tracks shared
|
||||
and exclusive references at runtime and panics if they are misused.
|
||||
## `RefCell`
|
||||
|
||||
```rust,editable
|
||||
use std::cell::RefCell;
|
||||
@ -56,16 +47,34 @@ fn main() {
|
||||
}
|
||||
```
|
||||
|
||||
## `Cell`
|
||||
|
||||
`Cell` wraps a value and allows getting or setting the value, even with a shared
|
||||
reference to the `Cell`. However, it does not allow any references to the value.
|
||||
Since there are no references, borrowing rules cannot be broken.
|
||||
|
||||
<details>
|
||||
|
||||
- If we were using `Cell` instead of `RefCell` in this example, we would have to
|
||||
move the `Node` out of the `Rc` to push children, then move it back in. This
|
||||
is safe because there's always one, un-referenced value in the cell, but it's
|
||||
not ergonomic.
|
||||
- To do anything with a Node, you must call a `RefCell` method, usually `borrow`
|
||||
or `borrow_mut`.
|
||||
The main thing to take away from this slide is that Rust provides _safe_ ways to
|
||||
modify data behind a shared reference. There are a variety of ways to ensure
|
||||
that safety, and `RefCell` and `Cell` are two of them.
|
||||
|
||||
- `RefCell` enforces Rust's usual borrowing rules (either multiple shared
|
||||
references or a single exclusive reference) with a runtime check. In this
|
||||
case, all borrows are very short and never overlap, so the checks always
|
||||
succeed.
|
||||
|
||||
- `Rc` only allows shared (read-only) access to its contents, since its purpose
|
||||
is to allow (and count) many references. But we want to modify the value, so
|
||||
we need interior mutability.
|
||||
|
||||
- `Cell` is a simpler means to ensure safety: it has a `set` method that takes
|
||||
`&self`. This needs no runtime check, but requires moving values, which can
|
||||
have its own cost.
|
||||
|
||||
- Demonstrate that reference loops can be created by adding `root` to
|
||||
`subtree.children` (don't try to print it!).
|
||||
`subtree.children`.
|
||||
|
||||
- To demonstrate a runtime panic, add a `fn inc(&mut self)` that increments
|
||||
`self.value` and calls the same method on its children. This will panic in the
|
||||
presence of the reference loop, with
|
||||
|
@ -1,7 +1,8 @@
|
||||
# `Mutex`
|
||||
|
||||
[`Mutex<T>`][1] ensures mutual exclusion _and_ allows mutable access to `T`
|
||||
behind a read-only interface:
|
||||
behind a read-only interface (another form of
|
||||
[interior mutability](../../borrowing/interior-mutability)):
|
||||
|
||||
```rust,editable
|
||||
use std::sync::Mutex;
|
||||
|
Loading…
x
Reference in New Issue
Block a user