Skip to content

Commit 4205f97

Browse files
committed
---
yaml --- r: 55846 b: refs/heads/master c: 195911f h: refs/heads/master v: v3
1 parent 43647d7 commit 4205f97

File tree

2 files changed

+69
-1
lines changed

2 files changed

+69
-1
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
refs/heads/master: 721e1143a560e01694f88b53ddd9cfea1c6c7077
2+
refs/heads/master: 195911fca412527472233aee163782c3bca11517
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
44
refs/heads/snap-stage3: 79a2b2eafc3c766cecec8a5f76317693bae9ed17
55
refs/heads/try: 8eb2bab100b42f0ba751552d8eff00eb2134c55a

trunk/doc/tutorial-ffi.md

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,74 @@ pub fn uncompress(src: &[u8]) -> Option<~[u8]> {
139139
For reference, the examples used here are also available as an [library on
140140
GitHub](https://github.com/thestinger/rust-snappy).
141141

142+
# Destructors
143+
144+
Foreign libraries often hand off ownership of resources to the calling code,
145+
which should be wrapped in a destructor to provide safety and guarantee their
146+
release.
147+
148+
A type with the same functionality as owned boxes can be implemented by
149+
wrapping `malloc` and `free`:
150+
151+
~~~~
152+
use core::libc::{c_void, size_t, malloc, free};
153+
154+
#[abi = "rust-intrinsic"]
155+
extern "rust-intrinsic" mod rusti {
156+
fn init<T>() -> T;
157+
}
158+
159+
// a wrapper around the handle returned by the foreign code
160+
pub struct Unique<T> {
161+
priv ptr: *mut T
162+
}
163+
164+
pub impl<'self, T: Owned> Unique<T> {
165+
fn new(value: T) -> Unique<T> {
166+
unsafe {
167+
let ptr = malloc(core::sys::size_of::<T>() as size_t) as *mut T;
168+
assert!(!ptr::is_null(ptr));
169+
*ptr = value;
170+
Unique{ptr: ptr}
171+
}
172+
}
173+
174+
// the 'self lifetime results in the same semantics as `&*x` with ~T
175+
fn borrow(&self) -> &'self T {
176+
unsafe { cast::transmute(self.ptr) }
177+
}
178+
179+
// the 'self lifetime results in the same semantics as `&mut *x` with ~T
180+
fn borrow_mut(&mut self) -> &'self mut T {
181+
unsafe { cast::transmute(self.ptr) }
182+
}
183+
}
184+
185+
#[unsafe_destructor]
186+
impl<T: Owned> Drop for Unique<T> {
187+
fn finalize(&self) {
188+
unsafe {
189+
let mut x = rusti::init(); // dummy value to swap in
190+
x <-> *self.ptr; // moving the object out is needed to call the destructor
191+
free(self.ptr as *c_void)
192+
}
193+
}
194+
}
195+
196+
// A comparison between the built-in ~ and this reimplementation
197+
fn main() {
198+
{
199+
let mut x = ~5;
200+
*x = 10;
201+
} // `x` is freed here
202+
203+
{
204+
let mut y = Unique::new(5);
205+
*y.borrow_mut() = 10;
206+
} // `y` is freed here
207+
}
208+
~~~~
209+
142210
# Linking
143211

144212
In addition to the `#[link_args]` attribute for explicitly passing arguments to the linker, an

0 commit comments

Comments
 (0)