Skip to content

Commit

Permalink
stdlib: Implement some preliminary libuv bindings
Browse files Browse the repository at this point in the history
std::uv is intended to be low-level, exactly mirroring the C API.
Difficult to continue the implementation now without scheduler
improvements.
  • Loading branch information
brson committed Dec 1, 2011
1 parent b2fd612 commit 7476a39
Show file tree
Hide file tree
Showing 9 changed files with 284 additions and 2 deletions.
1 change: 1 addition & 0 deletions mk/rt.mk
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down
23 changes: 23 additions & 0 deletions src/etc/x86.supp
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
4 changes: 4 additions & 0 deletions src/lib/ctypes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
3 changes: 2 additions & 1 deletion src/lib/std.rc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -46,6 +46,7 @@ mod net;
mod run;
mod sys;
mod task;
mod uv;


// Utility modules
Expand Down
150 changes: 150 additions & 0 deletions src/lib/uv.rs
Original file line number Diff line number Diff line change
@@ -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 changes: 50 additions & 0 deletions src/rt/rust_uv.cpp
Original file line number Diff line number Diff line change
@@ -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);
}
10 changes: 9 additions & 1 deletion src/rt/rustrt.def.in
Original file line number Diff line number Diff line change
Expand Up @@ -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
1 change: 1 addition & 0 deletions src/test/stdtest/stdtest.rc
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ mod tri;
mod treemap;
mod uint;
mod unsafe;
mod uv;
mod vec;

// Local Variables:
Expand Down
44 changes: 44 additions & 0 deletions src/test/stdtest/uv.rs
Original file line number Diff line number Diff line change
@@ -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);
*/
}
}

0 comments on commit 7476a39

Please sign in to comment.