From c2eb084b4c273682b06fcaf285399ec9bf6fd0cb Mon Sep 17 00:00:00 2001 From: Joshua Wise Date: Wed, 23 Nov 2011 05:15:04 -0500 Subject: [PATCH] Add c_vec library to std. --- src/lib/c_vec.rs | 98 ++++++++++++++++++++++++++++++++++++++++++++++++ src/lib/std.rc | 3 +- 2 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 src/lib/c_vec.rs diff --git a/src/lib/c_vec.rs b/src/lib/c_vec.rs new file mode 100644 index 000000000000..3b94c54f3736 --- /dev/null +++ b/src/lib/c_vec.rs @@ -0,0 +1,98 @@ +/* +Module: c_vec + +Library to interface with chunks of memory allocated in C. + +It is often desirable to safely interface with memory allocated from C, +encapsulating the unsafety into allocation and destruction time. Indeed, +allocating memory externally is currently the only way to give Rust shared +mutable state with C programs that keep their own references; vectors are +unsuitable because they could be reallocated or moved at any time, and +importing C memory into a vector takes a one-time snapshot of the memory. + +This module simplifies the usage of such external blocks of memory. Memory +is encapsulated into an opaque object after creation; the lifecycle of the +memory can be optionally managed by Rust, if an appropriate destructor +closure is provided. Safety is ensured by bounds-checking accesses, which +are marshalled through get and set functions. + +There are three unsafe functions: the two introduction forms, and the +pointer elimination form. The introduction forms are unsafe for the obvious +reason (they act on a pointer that cannot be checked inside the method), but +the elimination form is somewhat more subtle in its unsafety. By using a +pointer taken from a c_vec::t without keeping a reference to the c_vec::t +itself around, the c_vec could be garbage collected, and the memory within +could be destroyed. There are legitimate uses for the pointer elimination +form -- for instance, to pass memory back into C -- but great care must be +taken to ensure that a reference to the c_vec::t is still held if needed. + + */ + +export t; +export create, create_with_dtor; +export get, set; +export size; +export ptr; + +/* + Type: t + + The type representing a native chunk of memory. Wrapped in a tag for + opacity; FIXME #818 when it is possible to have truly opaque types, this + should be revisited. + */ + +tag t { + t({ base: *T, size: uint, rsrc: @dtor_res}); +} + +resource dtor_res(dtor: option::t) { + alt dtor { + option::none. { } + option::some(f) { f(); } + } +} + +/* + Section: Introduction forms + */ + +unsafe fn create(base: *T, size: uint) -> t { + ret t({base: base, + size: size, + rsrc: @dtor_res(option::none) + }); +} + +unsafe fn create_with_dtor(base: *T, size: uint, dtor: fn@()) -> t { + ret t({base: base, + size: size, + rsrc: @dtor_res(option::some(dtor)) + }); +} + +/* + Section: Operations + */ + +fn get(t: t, ofs: uint) -> T { + assert ofs < (*t).size; + ret unsafe { *ptr::offset((*t).base, ofs) }; +} + +fn set(t: t, ofs: uint, v: T) { + assert ofs < (*t).size; + unsafe { *(ptr::offset((*t).base, ofs) as *mutable T) = v }; +} + +/* + Section: Elimination forms + */ + +fn size(t: t) -> uint { + ret (*t).size; +} + +unsafe fn ptr(t: t) -> *T { + ret (*t).base; +} diff --git a/src/lib/std.rc b/src/lib/std.rc index 342e3fe394d1..555828f79c3f 100644 --- a/src/lib/std.rc +++ b/src/lib/std.rc @@ -10,7 +10,7 @@ export box, char, float, int, str, ptr; export uint, u8, u32, u64, vec, bool; export comm, fs, io, net, run, sys, task; -export ctypes, either, option, result, four, tri, util; +export c_vec, ctypes, either, option, result, four, tri, util; export bitv, deque, fun_treemap, list, map, smallintmap, sort, treemap, ufind; export rope; export math, math_f32, math_f64; @@ -50,6 +50,7 @@ mod task; // Utility modules +mod c_vec; mod ctypes; mod cmath; /* unexported */ mod either;