about summary refs log tree commit diff
path: root/src/rt/rust_uv.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/rt/rust_uv.cpp')
-rw-r--r--src/rt/rust_uv.cpp186
1 files changed, 159 insertions, 27 deletions
diff --git a/src/rt/rust_uv.cpp b/src/rt/rust_uv.cpp
index 9ee1b844add..03cd75d4805 100644
--- a/src/rt/rust_uv.cpp
+++ b/src/rt/rust_uv.cpp
@@ -1,51 +1,183 @@
 #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
- */
+// crust fn pointers
+typedef void (*crust_async_op_cb)(uv_loop_t* loop, void* data);
+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);
 
-extern "C" CDECL uv_loop_t*
-rust_uv_default_loop() {
-  return uv_default_loop();
+// 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);
+}
+
+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);
 }
 
-extern "C" CDECL uv_loop_t*
+static void
+native_close_op_cb(uv_handle_t* op_handle) {
+  uv_loop_t* loop = op_handle->loop;
+  current_kernel_free(op_handle);
+  loop->data = 0; // a ptr to some stack-allocated rust mem
+  uv_loop_delete(loop);
+}
+
+// native fns bound in rust
+extern "C" void*
 rust_uv_loop_new() {
-  return uv_loop_new();
+    return (void*)uv_loop_new();
+}
+
+extern "C" void
+rust_uv_loop_set_data(uv_loop_t* loop, void* data) {
+    loop->data = data;
 }
 
-extern "C" CDECL void
-rust_uv_loop_delete(uv_loop_t *loop) {
-  return uv_loop_delete(loop);
+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" CDECL int
-rust_uv_run(uv_loop_t *loop) {
-  return uv_run(loop);
+extern "C" void
+rust_uv_stop_op_cb(uv_handle_t* op_handle) {
+  /*  // this is a hack to get libuv to cleanup a
+  // handle that was made to not prevent the loop
+  // from exiting via uv_unref().
+  uv_ref(op_handle->loop);
+  uv_close(op_handle, native_close_op_cb);
+  uv_run(op_handle->loop); // this should process the handle's
+                           // close event and then return
+						   */
+  // the above code is supposed to work to cleanly close
+  // a handler that was uv_unref()'d. but it causes much spew
+  // instead. this is the ugly/quick way to deal w/ it for now.
+  uv_close(op_handle, native_close_op_cb);
+  native_close_op_cb(op_handle);
 }
 
-extern "C" CDECL void
-rust_uv_unref(uv_loop_t *loop) {
-  return uv_unref(loop);
+extern "C" void
+rust_uv_run(uv_loop_t* loop) {
+	uv_run(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" 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" CDECL int
-rust_uv_idle_start(uv_idle_t* idle, uv_idle_cb cb) {
-  return uv_idle_start(idle, 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" CDECL size_t
-rust_uv_size_of_idle_t() {
-  return sizeof(uv_idle_t);
+extern "C" void
+rust_uv_timer_stop(uv_timer_t* the_timer) {
+  uv_timer_stop(the_timer); 
 }