Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: begin a "low-level & unsafe code" guide. #12887

Merged
merged 1 commit into from
Mar 15, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion mk/docs.mk
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@
DOCS := index tutorial guide-ffi guide-macros guide-lifetimes \
guide-tasks guide-container guide-pointers guide-testing \
guide-runtime complement-bugreport complement-cheatsheet \
complement-lang-faq complement-project-faq rust rustdoc
complement-lang-faq complement-project-faq rust rustdoc \
guide-unsafe

PDF_DOCS := tutorial rust

Expand Down
79 changes: 0 additions & 79 deletions src/doc/guide-ffi.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,85 +170,6 @@ Foreign libraries often hand off ownership of resources to the calling code.
When this occurs, we must use Rust's destructors to provide safety and guarantee
the release of these resources (especially in the case of failure).

As an example, we give a reimplementation of owned boxes by wrapping `malloc`
and `free`:

~~~~
use std::cast;
use std::libc::{c_void, size_t, malloc, free};
use std::mem;
use std::ptr;

// Define a wrapper around the handle returned by the foreign code.
// Unique<T> has the same semantics as ~T
pub struct Unique<T> {
// It contains a single raw, mutable pointer to the object in question.
priv ptr: *mut T
}

// Implement methods for creating and using the values in the box.
// NB: For simplicity and correctness, we require that T has kind Send
// (owned boxes relax this restriction, and can contain managed (GC) boxes).
// This is because, as implemented, the garbage collector would not know
// about any shared boxes stored in the malloc'd region of memory.
impl<T: Send> Unique<T> {
pub fn new(value: T) -> Unique<T> {
unsafe {
let ptr = malloc(std::mem::size_of::<T>() as size_t) as *mut T;
assert!(!ptr.is_null());
// `*ptr` is uninitialized, and `*ptr = value` would attempt to destroy it
// move_val_init moves a value into this memory without
// attempting to drop the original value.
mem::move_val_init(&mut *ptr, value);
Unique{ptr: ptr}
}
}

// the 'r lifetime results in the same semantics as `&*x` with ~T
pub fn borrow<'r>(&'r self) -> &'r T {
unsafe { cast::copy_lifetime(self, &*self.ptr) }
}

// the 'r lifetime results in the same semantics as `&mut *x` with ~T
pub fn borrow_mut<'r>(&'r mut self) -> &'r mut T {
unsafe { cast::copy_mut_lifetime(self, &mut *self.ptr) }
}
}

// The key ingredient for safety, we associate a destructor with
// Unique<T>, making the struct manage the raw pointer: when the
// struct goes out of scope, it will automatically free the raw pointer.
// NB: This is an unsafe destructor, because rustc will not normally
// allow destructors to be associated with parametrized types, due to
// bad interaction with managed boxes. (With the Send restriction,
// we don't have this problem.)
#[unsafe_destructor]
impl<T: Send> Drop for Unique<T> {
fn drop(&mut self) {
unsafe {
let x = mem::uninit(); // dummy value to swap in
// We need to move the object out of the box, so that
// the destructor is called (at the end of this scope.)
ptr::replace(self.ptr, x);
free(self.ptr as *mut c_void)
}
}
}

// A comparison between the built-in ~ and this reimplementation
fn main() {
{
let mut x = ~5;
*x = 10;
} // `x` is freed here

{
let mut y = Unique::new(5);
*y.borrow_mut() = 10;
} // `y` is freed here
}
~~~~

# Callbacks from C code to Rust functions

Some external libraries require the usage of callbacks to report back their
Expand Down
Loading