Repository navigation
Chapter 3 Section 12: Resource Management First draft. - #79
sofiabelen wants to merge 6 commits into
Conversation
1989ee9 to
95d147e
Compare
|
I left out a side note on move semantics/return value optimization as it seemed out of scope (but might be interesting to add):
|
|
I've also left out the part on struct field drop order. It optionally be added as a short remark: Dropping the |
0f46055 to
ef5e78c
Compare
daxhuiberts
left a comment
There was a problem hiding this comment.
I think we almost have the right structure.
Fine tune that a little bit, and then we can focus on improving the text to be clearer and less LLMy.
| Our `Store` needs three resources: a data file, an index loaded from that file, | ||
| and a journal. Here is `open_store` in C: |
There was a problem hiding this comment.
Explain the purpose of open_store and what the intent is.
| Acquiring a resource, such as memory, a file, or a lock, comes with an | ||
| obligation to release it. When several are acquired in a row and each may depend | ||
| on the previous one, a failure partway through leaves some held and others | ||
| never acquired. Exactly the ones that are held must be released, so what needs | ||
| cleaning up depends on where the failure happened. | ||
|
|
||
| C leaves that bookkeeping to the programmer, who has to write it out for every | ||
| failure point. Rust makes it a question of ownership: whoever owns a value is | ||
| responsible for releasing it, and the compiler tracks who that is. |
There was a problem hiding this comment.
This intro is still a bit cryptic/LLMy. Can you clarify it a bit more.
| ### RAII and `Drop` | ||
|
|
||
| *Resource Acquisition Is Initialization* (RAII) ties resource management to an | ||
| object's lifetime: allocate on initialization, deallocate on destruction. | ||
|
|
||
| A type can implement the `Drop` trait to specify what happens when a value | ||
| is dropped. A `File` closes its underlying file descriptor when it is dropped. | ||
| A value is dropped when its owner goes out of scope, which is what happens | ||
| on an early return. Local variables are dropped in reverse order of declaration, | ||
| so the cleanup happens automatically in the correct order. |
There was a problem hiding this comment.
I think the purpose of this section is good, but can use a clearer explanation.
| > **One caveat:** `drop` cannot return an error, so a failure during cleanup is | ||
| > silently ignored. If callers need to know about such failures, give the type | ||
| > an explicit close method that returns a `Result`. |
There was a problem hiding this comment.
While true, let's skip this.
| ## What happens on success? | ||
|
|
||
| On success, the C function returns `BM_OK` before reaching the labels, so the | ||
| resources stay open. The caller must close them later: | ||
|
|
||
| ```c | ||
| void store_close(struct Store *store) { | ||
| journal_close(store->journal); | ||
| index_free(store->index); | ||
| fclose(store->file); | ||
| } | ||
| ``` | ||
|
|
||
| In Rust, returning transfers ownership of the resources to the caller: | ||
|
|
||
| ```rust,no-run | ||
| Ok(Store { journal, index, file }) | ||
| ``` | ||
|
|
||
| Putting `journal`, `index`, and `file` into the `Store` *moves* them. After a move, | ||
| the original variable no longer owns the value, so the function doesn't drop | ||
| those three locals when it returns. The `Store` owns them now, and `Ok(...)` | ||
| hands the `Store` to the caller. | ||
|
|
||
| This is the Rust counterpart of returning before the labels. Since a moved value | ||
| is never dropped by its old owner, it can never be dropped twice. | ||
|
|
||
| The resources then live as long as the caller's `Store` does: | ||
|
|
||
| ```rust,no-run | ||
| { | ||
| let store = open_store(Path::new("bookmarks.db"))?; | ||
| // ... use `store` ... | ||
| } // `store` goes out of scope here: its fields are dropped | ||
| ``` |
There was a problem hiding this comment.
I don't think this is needed. Let's keep the focus on the 'replace goto with ? and drop'.
| When `Index::load` fails, `?` returns early and `file` is closed automatically. | ||
| When `Journal::open` fails, `index` and then `file` are released. But how does | ||
| that work behind the scenes? |
There was a problem hiding this comment.
This one is also important and possibly warrants it's own tiny section. ? early returns and thus has roughly the same effect as the goto.
b5e6d8e to
7a6c1b5
Compare
|
@daxhuiberts Looks like most of your comments were addressed by new pushes. Could you briefly follow up? @sofiabelen Could you please run |
|
@sofiabelen Sorry, but you need to redo the dprint. We merged some changes to main that alters the C code style. |
…back to avoid duplicating code snippets, reduce noise in snippets, limit explanations of basic concepts and skip 'struct field order drop' as it's out of scope.
… removing the section on 'What happens on success?', clarifying some parts and reworking the example.
2c77dde to
106387c
Compare
Done, should be good now : ) |
No description provided.