b4c88cdcec
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().
176 lines
4.1 KiB
C++
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);
|
|
}
|
|
|