Skip to content

Commit 0d9c0c9

Browse files
committed
auto merge of #10822 : ezyang/rust/master, r=huonw
Signed-off-by: Edward Z. Yang <[email protected]>
2 parents 3c399f6 + b3e54d5 commit 0d9c0c9

File tree

1 file changed

+26
-9
lines changed

1 file changed

+26
-9
lines changed

doc/tutorial-ffi.md

+26-9
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ for the rust task is plenty for the C function to have.
152152

153153
A planned future improvement (net yet implemented at the time of this writing)
154154
is 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
156156
for this unmapped page is to prevent infinite recursion in C from overflowing
157157
onto other rust stacks. If the guard page is hit, then the process will be
158158
terminated 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
~~~~
177177
use std::cast;
178178
use std::libc::{c_void, size_t, malloc, free};
179179
use std::ptr;
180180
use 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
183184
pub 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.
187194
impl<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]
210226
impl<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

Comments
 (0)