diff --git a/SUMMARY.md b/SUMMARY.md index d8b3487..a7014d7 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -27,7 +27,7 @@ * [Checked](checked-uninit.md) * [Drop Flags](drop-flags.md) * [Unchecked](unchecked-uninit.md) -* [Ownership-Oriented Resource Management](raii.md) +* [Ownership Based Resource Management](obrm.md) * [Constructors](constructors.md) * [Destructors](destructors.md) * [Leaking](leaking.md) diff --git a/destructors.md b/destructors.md index e146ae4..34c8b2b 100644 --- a/destructors.md +++ b/destructors.md @@ -45,8 +45,8 @@ impl Drop for Box { ``` and this works fine because when Rust goes to drop the `ptr` field it just sees -a *mut that has no actual `Drop` implementation. Similarly nothing can use- -after-free the `ptr` because the Box is immediately marked as uninitialized. +a [Unique][] that has no actual `Drop` implementation. Similarly nothing can +use-after-free the `ptr` because when drop exits, it becomes inacessible. However this wouldn't work: @@ -174,3 +174,5 @@ arbitrarily invalid state in there. On balance this is an ok choice. Certainly what you should reach for by default. However, in the future we expect there to be a first-class way to announce that a field shouldn't be automatically dropped. + +[Unique]: phantom-data.html diff --git a/leaking.md b/leaking.md index bb6f7bb..dcb03b1 100644 --- a/leaking.md +++ b/leaking.md @@ -8,14 +8,17 @@ is perfect and all of our problems are solved. Everything is terrible and we have new and exotic problems to try to solve. -Many people like to believe that Rust eliminates resource leaks, but this is -absolutely not the case, no matter how you look at it. In the strictest sense, -"leaking" is so abstract as to be unpreventable. It's quite trivial to -initialize a collection at the start of a program, fill it with tons of objects -with destructors, and then enter an infinite event loop that never refers to it. -The collection will sit around uselessly, holding on to its precious resources -until the program terminates (at which point all those resources would have been -reclaimed by the OS anyway). +Many people like to believe that Rust eliminates resource leaks. In practice, +this is basically true. You would be surprised to see a Safe Rust program +leak resources in an uncontrolled way. + +However from a theoretical perspective this is absolutely not the case, no +matter how you look at it. In the strictest sense, "leaking" is so abstract as +to be unpreventable. It's quite trivial to initialize a collection at the start +of a program, fill it with tons of objects with destructors, and then enter an +infinite event loop that never refers to it. The collection will sit around +uselessly, holding on to its precious resources until the program terminates (at +which point all those resources would have been reclaimed by the OS anyway). We may consider a more restricted form of leak: failing to drop a value that is unreachable. Rust also doesn't prevent this. In fact Rust has a *function for @@ -181,7 +184,26 @@ in memory. ## thread::scoped::JoinGuard The thread::scoped API intends to allow threads to be spawned that reference -data on the stack without any synchronization over that data. Usage looked like: +data on their parent's stack without any synchronization over that data by +ensuring the parent joins the thread before any of the shared data goes out +of scope. + +```rust +pub fn scoped<'a, F>(f: F) -> JoinGuard<'a> + where F: FnOnce() + Send + 'a +``` + +Here `f` is some closure for the other thread to execute. Saying that +`F: Send +'a` is saying that it closes over data that lives for `'a`, and it +either owns that data or the data was Sync (implying `&data` is Send). + +Because JoinGuard has a lifetime, it keeps all the data it closes over +borrowed in the parent thread. This means the JoinGuard can't outlive +the data that the other thread is working on. When the JoinGuard *does* get +dropped it blocks the parent thread, ensuring the child terminates before any +of the closed-over data goes out of scope in the parent. + +Usage looked like: ```rust,ignore let mut data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; diff --git a/obrm.md b/obrm.md new file mode 100644 index 0000000..2c49524 --- /dev/null +++ b/obrm.md @@ -0,0 +1,14 @@ +% The Perils Of Ownership Based Resource Management (OBRM) + +OBRM (AKA RAII: Resource Acquisition Is Initialization) is something you'll +interact with a lot in Rust. Especially if you use the standard library. + +Roughly speaking the pattern is as follows: to acquire a resource, you create an +object that manages it. To release the resource, you simply destroy the object, +and it cleans up the resource for you. The most common "resource" this pattern +manages is simply *memory*. `Box`, `Rc`, and basically everything in +`std::collections` is a convenience to enable correctly managing memory. This is +particularly important in Rust because we have no pervasive GC to rely on for +memory management. Which is the point, really: Rust is about control. However we +are not limited to just memory. Pretty much every other system resource like a +thread, file, or socket is exposed through this kind of API. diff --git a/raii.md b/raii.md deleted file mode 100644 index e9b92c6..0000000 --- a/raii.md +++ /dev/null @@ -1,14 +0,0 @@ -% The Perils Of RAII - -Ownership Based Resource Management (AKA RAII: Resource Acquisition Is Initialization) is -something you'll interact with a lot in Rust. Especially if you use the standard library. - -Roughly speaking the pattern is as follows: to acquire a resource, you create an object that -manages it. To release the resource, you simply destroy the object, and it cleans up the -resource for you. The most common "resource" -this pattern manages is simply *memory*. `Box`, `Rc`, and basically everything in -`std::collections` is a convenience to enable correctly managing memory. This is particularly -important in Rust because we have no pervasive GC to rely on for memory management. Which is the -point, really: Rust is about control. However we are not limited to just memory. -Pretty much every other system resource like a thread, file, or socket is exposed through -this kind of API.