Skip to content

Commit 05f1818

Browse files
committed
---
yaml --- r: 56457 b: refs/heads/auto c: 195911f h: refs/heads/master i: 56455: 8fcd288 v: v3
1 parent c8f7069 commit 05f1818

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
@@ -14,6 +14,6 @@ refs/heads/try3: 9387340aab40a73e8424c48fd42f0c521a4875c0
1414
refs/tags/release-0.3.1: 495bae036dfe5ec6ceafd3312b4dca48741e845b
1515
refs/tags/release-0.4: e828ea2080499553b97dfe33b3f4d472b4562ad7
1616
refs/tags/release-0.5: 7e3bcfbf21278251ee936ad53e92e9b719702d73
17-
refs/heads/auto: 721e1143a560e01694f88b53ddd9cfea1c6c7077
17+
refs/heads/auto: 195911fca412527472233aee163782c3bca11517
1818
refs/heads/servo: af82457af293e2a842ba6b7759b70288da276167
1919
refs/tags/release-0.6: b4ebcfa1812664df5e142f0134a5faea3918544c

branches/auto/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)