@@ -152,7 +152,7 @@ for the rust task is plenty for the C function to have.
152
152
153
153
A planned future improvement (net yet implemented at the time of this writing)
154
154
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
156
156
for this unmapped page is to prevent infinite recursion in C from overflowing
157
157
onto other rust stacks. If the guard page is hit, then the process will be
158
158
terminated with a message saying that the guard page was hit.
@@ -166,39 +166,30 @@ the stack of the task which is spawned.
166
166
167
167
# Destructors
168
168
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) .
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.
172
172
173
- As an example, we give a reimplementation of owned boxes by wrapping ` malloc `
174
- and ` free ` :
173
+ A type with the same functionality as owned boxes can be implemented by
174
+ wrapping ` malloc ` and ` free ` :
175
175
176
176
~~~~
177
177
use std::cast;
178
178
use std::libc::{c_void, size_t, malloc, free};
179
179
use std::ptr;
180
180
use std::unstable::intrinsics;
181
181
182
- // Define a wrapper around the handle returned by the foreign code.
183
- // Unique<T> has the same semantics as ~T
182
+ // a wrapper around the handle returned by the foreign code
184
183
pub struct Unique<T> {
185
- // It contains a single raw, mutable pointer to the object in question.
186
184
priv ptr: *mut T
187
185
}
188
186
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.
194
187
impl<T: Send> Unique<T> {
195
188
pub fn new(value: T) -> Unique<T> {
196
189
unsafe {
197
190
let ptr = malloc(std::mem::size_of::<T>() as size_t) as *mut T;
198
191
assert!(!ptr::is_null(ptr));
199
192
// `*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.
202
193
intrinsics::move_val_init(&mut *ptr, value);
203
194
Unique{ptr: ptr}
204
195
}
@@ -215,20 +206,12 @@ impl<T: Send> Unique<T> {
215
206
}
216
207
}
217
208
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.)
225
209
#[unsafe_destructor]
226
210
impl<T: Send> Drop for Unique<T> {
227
211
fn drop(&mut self) {
228
212
unsafe {
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.)
213
+ let x = intrinsics::init(); // dummy value to swap in
214
+ // moving the object out is needed to call the destructor
232
215
ptr::replace_ptr(self.ptr, x);
233
216
free(self.ptr as *c_void)
234
217
}
0 commit comments