@@ -152,7 +152,7 @@ for the rust task is plenty for the C function to have.
152152
153153A planned future improvement (net yet implemented at the time of this writing)
154154is to have a guard page at the end of every rust stack. No rust function will
155- hit this guard page (due to rust 's usage of LLVM's __ morestack). The intention
155+ hit this guard page (due to Rust 's usage of LLVM's ` __morestack ` ). The intention
156156for this unmapped page is to prevent infinite recursion in C from overflowing
157157onto other rust stacks. If the guard page is hit, then the process will be
158158terminated with a message saying that the guard page was hit.
@@ -166,30 +166,39 @@ the stack of the task which is spawned.
166166
167167# Destructors
168168
169- Foreign libraries often hand off ownership of resources to the calling code,
170- which should be wrapped in a destructor to provide safety and guarantee their
171- release.
169+ Foreign libraries often hand off ownership of resources to the calling code.
170+ When this occurs, we must use Rust's destructors to provide safety and guarantee
171+ the release of these resources (especially in the case of failure) .
172172
173- A type with the same functionality as owned boxes can be implemented by
174- wrapping ` malloc ` and ` free ` :
173+ As an example, we give a reimplementation of owned boxes by wrapping ` malloc `
174+ and ` free ` :
175175
176176~~~~
177177use std::cast;
178178use std::libc::{c_void, size_t, malloc, free};
179179use std::ptr;
180180use std::unstable::intrinsics;
181181
182- // a wrapper around the handle returned by the foreign code
182+ // Define a wrapper around the handle returned by the foreign code.
183+ // Unique<T> has the same semantics as ~T
183184pub struct Unique<T> {
185+ // It contains a single raw, mutable pointer to the object in question.
184186 priv ptr: *mut T
185187}
186188
189+ // Implement methods for creating and using the values in the box.
190+ // NB: For simplicity and correctness, we require that T has kind Send
191+ // (owned boxes relax this restriction, and can contain managed (GC) boxes).
192+ // This is because, as implemented, the garbage collector would not know
193+ // about any shared boxes stored in the malloc'd region of memory.
187194impl<T: Send> Unique<T> {
188195 pub fn new(value: T) -> Unique<T> {
189196 unsafe {
190197 let ptr = malloc(std::mem::size_of::<T>() as size_t) as *mut T;
191198 assert!(!ptr::is_null(ptr));
192199 // `*ptr` is uninitialized, and `*ptr = value` would attempt to destroy it
200+ // move_val_init moves a value into this memory without
201+ // attempting to drop the original value.
193202 intrinsics::move_val_init(&mut *ptr, value);
194203 Unique{ptr: ptr}
195204 }
@@ -206,12 +215,20 @@ impl<T: Send> Unique<T> {
206215 }
207216}
208217
218+ // The key ingredient for safety, we associate a destructor with
219+ // Unique<T>, making the struct manage the raw pointer: when the
220+ // struct goes out of scope, it will automatically free the raw pointer.
221+ // NB: This is an unsafe destructor, because rustc will not normally
222+ // allow destructors to be associated with parametrized types, due to
223+ // bad interaction with managed boxes. (With the Send restriction,
224+ // we don't have this problem.)
209225#[unsafe_destructor]
210226impl<T: Send> Drop for Unique<T> {
211227 fn drop(&mut self) {
212228 unsafe {
213- let x = intrinsics::init(); // dummy value to swap in
214- // moving the object out is needed to call the destructor
229+ let x = intrinsics::uninit(); // dummy value to swap in
230+ // We need to move the object out of the box, so that
231+ // the destructor is called (at the end of this scope.)
215232 ptr::replace_ptr(self.ptr, x);
216233 free(self.ptr as *c_void)
217234 }
0 commit comments