rust/src/rt/rust_uv.cpp
Jeff Olson b4c88cdcec add uv::loop_delete()
because of the last change, the loop ptr is no longer cleaned up
when the loop exits. This api call addresses that. Sadly, the loop
ptr is not "reusable" across multiple calls to uv::run().
2012-02-28 17:56:15 -08:00

176 lines
4.1 KiB
C++

#include "rust_internal.h"
#include "uv.h"
// crust fn pointers
typedef void (*crust_async_op_cb)(uv_loop_t* loop, void* data,
uv_async_t* op_handle);
typedef void (*crust_simple_cb)(uint8_t* id_buf, void* loop_data);
typedef void (*crust_close_cb)(uint8_t* id_buf, void* handle,
void* data);
// data types
#define RUST_UV_HANDLE_LEN 16
struct handle_data {
uint8_t id_buf[RUST_UV_HANDLE_LEN];
crust_simple_cb cb;
crust_close_cb close_cb;
};
// helpers
static void*
current_kernel_malloc(size_t size, const char* tag) {
void* ptr = rust_task_thread::get_task()->kernel->malloc(size, tag);
return ptr;
}
static void
current_kernel_free(void* ptr) {
rust_task_thread::get_task()->kernel->free(ptr);
}
static handle_data*
new_handle_data_from(uint8_t* buf, crust_simple_cb cb) {
handle_data* data = (handle_data*)current_kernel_malloc(
sizeof(handle_data),
"handle_data");
memcpy(data->id_buf, buf, RUST_UV_HANDLE_LEN);
data->cb = cb;
return data;
}
// libuv callback impls
static void
native_crust_async_op_cb(uv_async_t* handle, int status) {
crust_async_op_cb cb = (crust_async_op_cb)handle->data;
void* loop_data = handle->loop->data;
cb(handle->loop, loop_data, handle);
}
static void
native_async_cb(uv_async_t* handle, int status) {
handle_data* handle_d = (handle_data*)handle->data;
void* loop_data = handle->loop->data;
handle_d->cb(handle_d->id_buf, loop_data);
}
static void
native_timer_cb(uv_timer_t* handle, int status) {
handle_data* handle_d = (handle_data*)handle->data;
void* loop_data = handle->loop->data;
handle_d->cb(handle_d->id_buf, loop_data);
}
static void
native_close_cb(uv_handle_t* handle) {
handle_data* data = (handle_data*)handle->data;
data->close_cb(data->id_buf, handle, handle->loop->data);
}
static void
native_close_op_cb(uv_handle_t* op_handle) {
current_kernel_free(op_handle);
// uv_run() should return after this..
}
// native fns bound in rust
extern "C" void*
rust_uv_loop_new() {
return (void*)uv_loop_new();
}
extern "C" void
rust_uv_loop_delete(uv_loop_t* loop) {
uv_loop_delete(loop);
}
extern "C" void
rust_uv_loop_set_data(uv_loop_t* loop, void* data) {
loop->data = data;
}
extern "C" void*
rust_uv_bind_op_cb(uv_loop_t* loop, crust_async_op_cb cb) {
uv_async_t* async = (uv_async_t*)current_kernel_malloc(
sizeof(uv_async_t),
"uv_async_t");
uv_async_init(loop, async, native_crust_async_op_cb);
async->data = (void*)cb;
// decrement the ref count, so that our async bind
// doesn't count towards keeping the loop alive
//uv_unref(loop);
return async;
}
extern "C" void
rust_uv_stop_op_cb(uv_handle_t* op_handle) {
uv_close(op_handle, native_close_op_cb);
}
extern "C" void
rust_uv_run(uv_loop_t* loop) {
uv_run(loop);
}
extern "C" void
rust_uv_close(uv_handle_t* handle, crust_close_cb cb) {
handle_data* data = (handle_data*)handle->data;
data->close_cb = cb;
uv_close(handle, native_close_cb);
}
extern "C" void
rust_uv_close_async(uv_async_t* handle) {
current_kernel_free(handle->data);
current_kernel_free(handle);
}
extern "C" void
rust_uv_close_timer(uv_async_t* handle) {
current_kernel_free(handle->data);
current_kernel_free(handle);
}
extern "C" void
rust_uv_async_send(uv_async_t* handle) {
uv_async_send(handle);
}
extern "C" void*
rust_uv_async_init(uv_loop_t* loop, crust_simple_cb cb,
uint8_t* buf) {
uv_async_t* async = (uv_async_t*)current_kernel_malloc(
sizeof(uv_async_t),
"uv_async_t");
uv_async_init(loop, async, native_async_cb);
handle_data* data = new_handle_data_from(buf, cb);
async->data = data;
return async;
}
extern "C" void*
rust_uv_timer_init(uv_loop_t* loop, crust_simple_cb cb,
uint8_t* buf) {
uv_timer_t* new_timer = (uv_timer_t*)current_kernel_malloc(
sizeof(uv_timer_t),
"uv_timer_t");
uv_timer_init(loop, new_timer);
handle_data* data = new_handle_data_from(buf, cb);
new_timer->data = data;
return new_timer;
}
extern "C" void
rust_uv_timer_start(uv_timer_t* the_timer, uint32_t timeout,
uint32_t repeat) {
uv_timer_start(the_timer, native_timer_cb, timeout, repeat);
}
extern "C" void
rust_uv_timer_stop(uv_timer_t* the_timer) {
uv_timer_stop(the_timer);
}