stdlib: Implement some preliminary libuv bindings

std::uv is intended to be low-level, exactly mirroring the C API.
Difficult to continue the implementation now without scheduler
improvements.
This commit is contained in:
Brian Anderson 2011-11-30 23:26:23 -08:00
parent b2fd6121c0
commit 7476a39e47
9 changed files with 284 additions and 2 deletions

View File

@ -47,6 +47,7 @@ RUNTIME_CS_$(1) := \
rt/rust_task_list.cpp \
rt/rust_port.cpp \
rt/rust_upcall.cpp \
rt/rust_uv.cpp \
rt/rust_log.cpp \
rt/rust_timer.cpp \
rt/circular_buffer.cpp \

View File

@ -364,3 +364,26 @@
fun:_Znwj
fun:_ZN4llvm4UsernwEjj
}
{
libuv-0-byte-realloc1
Memcheck:Leak
fun:malloc
fun:realloc
fun:ev_realloc_emul
fun:ev_realloc
fun:epoll_destroy
fun:ev_loop_destroy
fun:uv_loop_delete
}
{
libuv-0-byte-realloc2
Memcheck:Leak
fun:malloc
fun:realloc
fun:ev_realloc_emul
fun:ev_realloc
fun:ev_loop_destroy
fun:uv_loop_delete
}

View File

@ -6,6 +6,7 @@ Definitions useful for C interop
type c_int = i32;
type void = int; // Not really the same as C
type long = int;
type unsigned = u32;
type ulong = uint;
@ -23,3 +24,6 @@ type off_t = uint;
type fd_t = i32; // not actually a C type, but should be.
type pid_t = i32;
// enum is implementation-defined, but is 32-bits in practice
type enum = u32;

View File

@ -9,7 +9,7 @@
export box, char, float, int, str, ptr;
export uint, u8, u32, u64, vec, bool;
export comm, fs, io, net, run, sys, task;
export comm, fs, io, net, run, sys, task, uv;
export c_vec, ctypes, either, option, result, four, tri, util;
export bitv, deque, fun_treemap, list, map, smallintmap, sort, treemap, ufind;
export rope;
@ -46,6 +46,7 @@ mod net;
mod run;
mod sys;
mod task;
mod uv;
// Utility modules

150
src/lib/uv.rs Normal file
View File

@ -0,0 +1,150 @@
/*
This is intended to be a low-level binding to libuv that very closely mimics
the C libuv API. Does very little right now pending scheduler improvements.
*/
#[cfg(target_os = "linux")];
#[cfg(target_os = "macos")];
export sanity_check;
export loop_t, idle_t;
export loop_new, loop_delete, default_loop, run, unref;
export idle_init, idle_start;
export idle_new;
#[link_name = "rustrt"]
native mod uv {
fn rust_uv_loop_new() -> *loop_t;
fn rust_uv_loop_delete(loop: *loop_t);
fn rust_uv_default_loop() -> *loop_t;
fn rust_uv_run(loop: *loop_t) -> ctypes::c_int;
fn rust_uv_unref(loop: *loop_t);
fn rust_uv_idle_init(loop: *loop_t, idle: *idle_t) -> ctypes::c_int;
fn rust_uv_idle_start(idle: *idle_t, cb: idle_cb) -> ctypes::c_int;
}
#[link_name = "rustrt"]
native mod helpers {
fn rust_uv_size_of_idle_t() -> ctypes::size_t;
}
type opaque_cb = *ctypes::void;
type handle_type = ctypes::enum;
type close_cb = opaque_cb;
type idle_cb = opaque_cb;
#[cfg(target_os = "linux")]
#[cfg(target_os = "macos")]
type handle_private_fields = {
a00: ctypes::c_int,
a01: ctypes::c_int,
a02: ctypes::c_int,
a03: ctypes::c_int,
a04: ctypes::c_int,
a05: ctypes::c_int,
a06: int,
a07: int,
a08: int,
a09: int,
a10: int,
a11: int,
a12: int
};
type handle_fields = {
loop: *loop_t,
type_: handle_type,
close_cb: close_cb,
data: *ctypes::void,
private: handle_private_fields
};
type handle_t = {
fields: handle_fields
};
type loop_t = int;
type idle_t = {
fields: handle_fields
/* private: idle_private_fields */
};
fn idle_init(loop: *loop_t, idle: *idle_t) -> ctypes::c_int {
uv::rust_uv_idle_init(loop, idle)
}
fn idle_start(idle: *idle_t, cb: idle_cb) -> ctypes::c_int {
uv::rust_uv_idle_start(idle, cb)
}
fn default_loop() -> *loop_t {
uv::rust_uv_default_loop()
}
fn loop_new() -> *loop_t {
uv::rust_uv_loop_new()
}
fn loop_delete(loop: *loop_t) {
uv::rust_uv_loop_delete(loop)
}
fn run(loop: *loop_t) -> ctypes::c_int {
uv::rust_uv_run(loop)
}
fn unref(loop: *loop_t) {
uv::rust_uv_unref(loop)
}
fn sanity_check() {
fn check_size(t: str, uv: ctypes::size_t, rust: ctypes::size_t) {
log #fmt("size of %s: uv: %u, rust: %u", t, uv, rust);
assert uv == rust;
}
check_size("idle_t",
helpers::rust_uv_size_of_idle_t(),
sys::size_of::<idle_t>());
}
#[cfg(target_os = "linux")]
#[cfg(target_os = "macos")]
fn handle_fields_new() -> handle_fields {
{
loop: ptr::null(),
type_: 0u32,
close_cb: ptr::null(),
data: ptr::null(),
private: {
a00: 0i32,
a01: 0i32,
a02: 0i32,
a03: 0i32,
a04: 0i32,
a05: 0i32,
a06: 0,
a07: 0,
a08: 0,
a09: 0,
a10: 0,
a11: 0,
a12: 0
}
}
}
fn idle_new() -> idle_t {
{
fields: handle_fields_new()
}
}

50
src/rt/rust_uv.cpp Normal file
View File

@ -0,0 +1,50 @@
#include "rust_internal.h"
#include "uv.h"
/*
Wrappers of uv_* functions. These can be eliminated by figuring
out how to build static uv with externs, or by just using dynamic libuv
*/
extern "C" CDECL uv_loop_t*
rust_uv_default_loop() {
return uv_default_loop();
}
extern "C" CDECL uv_loop_t*
rust_uv_loop_new() {
return uv_loop_new();
}
extern "C" CDECL void
rust_uv_loop_delete(uv_loop_t *loop) {
return uv_loop_delete(loop);
}
extern "C" CDECL int
rust_uv_run(uv_loop_t *loop) {
return uv_run(loop);
}
extern "C" CDECL void
rust_uv_unref(uv_loop_t *loop) {
return uv_unref(loop);
}
extern "C" CDECL int
rust_uv_idle_init(uv_loop_t* loop, uv_idle_t* idle) {
return uv_idle_init(loop, idle);
}
extern "C" CDECL int
rust_uv_idle_start(uv_idle_t* idle, uv_idle_cb cb) {
return uv_idle_start(idle, cb);
}
extern "C" CDECL size_t
rust_uv_size_of_idle_t() {
return sizeof(uv_idle_t);
}

View File

@ -68,4 +68,12 @@ upcall_vec_push
upcall_call_shim_on_c_stack
upcall_new_stack
upcall_del_stack
asm_call_on_stack
asm_call_on_stack
rust_uv_default_loop
rust_uv_loop_new
rust_uv_loop_delete
rust_uv_run
rust_uv_unref
rust_uv_idle_init
rust_uv_idle_start
rust_uv_size_of_idle_t

View File

@ -40,6 +40,7 @@ mod tri;
mod treemap;
mod uint;
mod unsafe;
mod uv;
mod vec;
// Local Variables:

44
src/test/stdtest/uv.rs Normal file
View File

@ -0,0 +1,44 @@
#[cfg(target_os = "linux")];
#[cfg(target_os = "macos")];
import std::uv;
import std::ptr;
#[test]
fn sanity_check() {
uv::sanity_check();
}
// From test-ref.c
mod test_ref {
#[test]
fn ref() {
let loop = uv::loop_new();
uv::run(loop);
uv::loop_delete(loop);
}
#[test]
fn idle_ref() {
let loop = uv::loop_new();
let h = uv::idle_new();
uv::idle_init(loop, ptr::addr_of(h));
uv::idle_start(ptr::addr_of(h), ptr::null());
uv::unref(loop);
uv::run(loop);
uv::loop_delete(loop);
}
#[test]
fn async_ref() {
/*
let loop = uv::loop_new();
let h = uv::async_new();
uv::async_init(loop, ptr::addr_of(h), ptr::null());
uv::unref(loop);
uv::run(loop);
uv::loop_delete(loop);
*/
}
}