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:
parent
b2fd6121c0
commit
7476a39e47
1
mk/rt.mk
1
mk/rt.mk
@ -47,6 +47,7 @@ RUNTIME_CS_$(1) := \
|
|||||||
rt/rust_task_list.cpp \
|
rt/rust_task_list.cpp \
|
||||||
rt/rust_port.cpp \
|
rt/rust_port.cpp \
|
||||||
rt/rust_upcall.cpp \
|
rt/rust_upcall.cpp \
|
||||||
|
rt/rust_uv.cpp \
|
||||||
rt/rust_log.cpp \
|
rt/rust_log.cpp \
|
||||||
rt/rust_timer.cpp \
|
rt/rust_timer.cpp \
|
||||||
rt/circular_buffer.cpp \
|
rt/circular_buffer.cpp \
|
||||||
|
@ -364,3 +364,26 @@
|
|||||||
fun:_Znwj
|
fun:_Znwj
|
||||||
fun:_ZN4llvm4UsernwEjj
|
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
|
||||||
|
}
|
||||||
|
@ -6,6 +6,7 @@ Definitions useful for C interop
|
|||||||
|
|
||||||
type c_int = i32;
|
type c_int = i32;
|
||||||
|
|
||||||
|
type void = int; // Not really the same as C
|
||||||
type long = int;
|
type long = int;
|
||||||
type unsigned = u32;
|
type unsigned = u32;
|
||||||
type ulong = uint;
|
type ulong = uint;
|
||||||
@ -23,3 +24,6 @@ type off_t = uint;
|
|||||||
|
|
||||||
type fd_t = i32; // not actually a C type, but should be.
|
type fd_t = i32; // not actually a C type, but should be.
|
||||||
type pid_t = i32;
|
type pid_t = i32;
|
||||||
|
|
||||||
|
// enum is implementation-defined, but is 32-bits in practice
|
||||||
|
type enum = u32;
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
export box, char, float, int, str, ptr;
|
export box, char, float, int, str, ptr;
|
||||||
export uint, u8, u32, u64, vec, bool;
|
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 c_vec, ctypes, either, option, result, four, tri, util;
|
||||||
export bitv, deque, fun_treemap, list, map, smallintmap, sort, treemap, ufind;
|
export bitv, deque, fun_treemap, list, map, smallintmap, sort, treemap, ufind;
|
||||||
export rope;
|
export rope;
|
||||||
@ -46,6 +46,7 @@ mod net;
|
|||||||
mod run;
|
mod run;
|
||||||
mod sys;
|
mod sys;
|
||||||
mod task;
|
mod task;
|
||||||
|
mod uv;
|
||||||
|
|
||||||
|
|
||||||
// Utility modules
|
// Utility modules
|
||||||
|
150
src/lib/uv.rs
Normal file
150
src/lib/uv.rs
Normal 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
50
src/rt/rust_uv.cpp
Normal 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);
|
||||||
|
}
|
@ -69,3 +69,11 @@ upcall_call_shim_on_c_stack
|
|||||||
upcall_new_stack
|
upcall_new_stack
|
||||||
upcall_del_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
|
@ -40,6 +40,7 @@ mod tri;
|
|||||||
mod treemap;
|
mod treemap;
|
||||||
mod uint;
|
mod uint;
|
||||||
mod unsafe;
|
mod unsafe;
|
||||||
|
mod uv;
|
||||||
mod vec;
|
mod vec;
|
||||||
|
|
||||||
// Local Variables:
|
// Local Variables:
|
||||||
|
44
src/test/stdtest/uv.rs
Normal file
44
src/test/stdtest/uv.rs
Normal 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);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user