Skip to content

RAII chapter for idiomatic rust #2820

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
Open

RAII chapter for idiomatic rust #2820

wants to merge 12 commits into from

Conversation

GlenDC
Copy link
Collaborator

@GlenDC GlenDC commented Jul 15, 2025

This PR adds the RAII chapter for the idiomatic Rust deep dive.

Copy link

google-cla bot commented Jul 15, 2025

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

Copy link
Collaborator

@randomPoison randomPoison left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks pretty good, there's lots of good stuff in this chapter 😁 I've got various feedback below, but it's definitely off to a good start!

@GlenDC
Copy link
Collaborator Author

GlenDC commented Jul 25, 2025

I started to action all feedback since today. I'll explicitly re-request reviews once I am done. Probably best not to review again until then.

@GlenDC GlenDC added the waiting for author Waiting on the issue author to reply label Jul 25, 2025
GlenDC added 4 commits July 26, 2025 15:11
- directly where possible
- otherwise as inline feedback as notes to take
  into account for next draft
refresher on `RAII` and
use the OS File Descriptor example to start
the discussions around RAII

all previous content is for now moved to `_old` for my own
reference, will add the new content based on the agreed upon
new structure next.
@GlenDC GlenDC marked this pull request as draft August 1, 2025 08:00
@GlenDC GlenDC removed the waiting for author Waiting on the issue author to reply label Aug 3, 2025
@GlenDC GlenDC marked this pull request as ready for review August 3, 2025 19:34
@GlenDC
Copy link
Collaborator Author

GlenDC commented Aug 3, 2025

The four slides in the RAII chapter are ready for review again.

Copy link
Collaborator

@randomPoison randomPoison left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking pretty good. The drop bomb and scope guard slides look good to me, my biggest suggestion is that we might want to split the mutex slide up so that it flows a bit better.

Comment on lines +90 to +92
- Insert `panic!("oops")` at the start of `read_to_end()` to show that `drop()`
still runs during unwinding. Rust guarantees this unless the panic strategy is
set to `abort`.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- Insert `panic!("oops")` at the start of `read_to_end()` to show that `drop()`
still runs during unwinding. Rust guarantees this unless the panic strategy is
set to `abort`.
- Insert `panic!("oops")` at the start of `read_to_end()` to show that `drop()`
still runs during unwinding.

You cover this in the next bullet point, so I think this one can be simplified.

Comment on lines +52 to +55
fn drop(&mut self) {
// [...]
println!("drop MutexGuard");
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is failing to demonstrate the crucial part of MutexGuard: That it reports back to the Mutex on drop, unlocking the mutex. I think we should have a stubbed-out unlock method on Mutex and call it on drop here.

Comment on lines +38 to +49
impl<'a, T> std::ops::Deref for MutexGuard<'a, T> {
type Target = T;
fn deref(&self) -> &T {
self.value
}
}

impl<'a, T> std::ops::DerefMut for MutexGuard<'a, T> {
fn deref_mut(&mut self) -> &mut T {
self.value
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For brevity I think we can omit the Deref impls from the example and have the code in main directly access guard.value. That's not an accurate depiction of how the actual MutexGuard works, but I think is good enough for us here.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've left a couple of comments in here about improving the example code, but I'd like to also propose a higher level change. I think we could split this slide in two, where the first slide would be "Mutex and MutexGuard" that just demonstrates using a mutex, i.e. what's in the main function on this slide. Then we'd have a second slide "Drop Guards" that shows the dummy implementation of Mutex and MutexGuard in order to show how to implement this pattern.

I think doing it that way would flow a bit better, because we would first show how the pattern is used, then dig into the details of how the pattern is implemented. It'd also allow us to slightly expand the example implementation to be a bit more detailed. Here's a playground link with a rough example of what the second slide would show. That doesn't compile currently because it's modifying a field of Mutex in a &self method. That could be fixed with atomics, which would be more accurate but would also add more clutter that I think would distract from the main point of demonstrating the general pattern of drop guards.

Comment on lines +88 to +100
## Poisoning

- If a thread panics while holding the lock, the value may be in a corrupt
state.

- To signal this, the standard library uses poisoning. When `Drop` runs during a
panic, the mutex marks itself as poisoned.

- On the next `lock()`, this shows up as an error. The caller must decide
whether to proceed or handle the error differently.

- See this example showing the standard library API with poisoning:
<https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=6fb0c2e9e5cbcbbae1c664f4650b8c92>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it's worth going into poisoning here. The point here is to demonstrate the drop guard pattern, not to talk in detail about how mutexes work.

Comment on lines +102 to +129
### Mutex Lock Lifecycle

```bob
+---------------+ +----------------------+
| Mutex<T> | lock | MutexGuard<T> |
| Unlocked | ------> | Exclusive Access |
+---------------+ +----------------------+

^ | drop
| no |
+---------------+ |
| |
| V

+---------------+ yes +-------------------+
| Mutex<T> | <---- | Thread panicking? |
| Poisoned | +-------------------+
+---------------+

|
| lock
|
v

+------------------+
| Err ( Poisoned ) |
+------------------+
```
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need this diagram, especially if we drop the discussion of poisoning as I suggested in another comment.

Copy link
Collaborator

@djmitche djmitche left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had a brief look at the updates since my last comments, and I'm happy enough!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants