diff --git a/src/libstd/uv.rs b/src/libstd/uv.rs index 0cc89a441ef..3988bd378d2 100644 --- a/src/libstd/uv.rs +++ b/src/libstd/uv.rs @@ -1,5 +1,6 @@ -export loop_new, run, close, run_in_bg, async_init, async_send, - timer_init, timer_start, timer_stop; +export loop_new, loop_delete, run, close, run_in_bg; +export async_init, async_send; +export timer_init, timer_start, timer_stop; // these are processed solely in the // process_operation() crust fn below @@ -44,11 +45,14 @@ type uv_loop_data = { rust_loop_chan: comm::chan }; -type uv_loop = comm::chan; +enum uv_loop { + uv_loop_new(comm::chan, *ctypes::void) +} #[nolink] native mod rustrt { fn rust_uv_loop_new() -> *ctypes::void; + fn rust_uv_loop_delete(loop: *ctypes::void); fn rust_uv_loop_set_data( loop: *ctypes::void, data: *uv_loop_data); @@ -103,7 +107,8 @@ fn loop_new() -> uv_loop unsafe { let rust_loop_chan = comm::chan::(rust_loop_port); // let the task-spawner return - comm::send(ret_recv_chan, copy(rust_loop_chan)); + let user_uv_loop = uv_loop_new(rust_loop_chan, loop_handle); + comm::send(ret_recv_chan, copy(user_uv_loop)); // create our "special" async handle that will // allow all operations against libuv to be @@ -225,7 +230,7 @@ fn loop_new() -> uv_loop unsafe { handles.insert(id, async_handle); let after_cb = after_cbs.get(id); after_cbs.remove(id); - let async = uv_async(id, rust_loop_chan); + let async = uv_async(id, user_uv_loop); id_to_handle.insert(id, copy(async)); task::spawn {|| after_cb(async); @@ -239,7 +244,8 @@ fn loop_new() -> uv_loop unsafe { uv_async_send(id) { let async_cb = async_cbs.get(id); task::spawn {|| - async_cb(uv_async(id, rust_loop_chan)); + let the_loop = user_uv_loop; + async_cb(uv_async(id, the_loop)); }; } @@ -254,7 +260,7 @@ fn loop_new() -> uv_loop unsafe { handles.insert(id, handle); let after_cb = after_cbs.get(id); after_cbs.remove(id); - let new_timer = uv_timer(id, rust_loop_chan); + let new_timer = uv_timer(id, user_uv_loop); id_to_handle.insert(id, copy(new_timer)); task::spawn {|| after_cb(new_timer); @@ -310,15 +316,22 @@ fn loop_new() -> uv_loop unsafe { ret comm::recv(ret_recv_port); } +fn loop_delete(loop: uv_loop) { + let loop_ptr = get_loop_ptr_from_uv_loop(loop); + rustrt::rust_uv_loop_delete(loop_ptr); +} + fn run(loop: uv_loop) { let end_port = comm::port::(); let end_chan = comm::chan::(end_port); - comm::send(loop, msg_run(end_chan)); + let loop_chan = get_loop_chan_from_uv_loop(loop); + comm::send(loop_chan, msg_run(end_chan)); comm::recv(end_port); } fn run_in_bg(loop: uv_loop) { - comm::send(loop, msg_run_in_bg); + let loop_chan = get_loop_chan_from_uv_loop(loop); + comm::send(loop_chan, msg_run_in_bg); } fn async_init ( @@ -326,13 +339,15 @@ fn async_init ( async_cb: fn~(uv_handle), after_cb: fn~(uv_handle)) { let msg = msg_async_init(async_cb, after_cb); - comm::send(loop, msg); + let loop_chan = get_loop_chan_from_uv_loop(loop); + comm::send(loop_chan, msg); } fn async_send(async: uv_handle) { alt async { uv_async(id, loop) { - comm::send(loop, msg_async_send(id)); + let loop_chan = get_loop_chan_from_uv_loop(loop); + comm::send(loop_chan, msg_async_send(id)); } _ { fail "attempting to call async_send() with a" + @@ -348,14 +363,16 @@ fn close(h: uv_handle, cb: fn~()) { fn timer_init(loop: uv_loop, after_cb: fn~(uv_handle)) { let msg = msg_timer_init(after_cb); - comm::send(loop, msg); + let loop_chan = get_loop_chan_from_uv_loop(loop); + comm::send(loop_chan, msg); } fn timer_start(the_timer: uv_handle, timeout: u32, repeat:u32, timer_cb: fn~(uv_handle)) { alt the_timer { - uv_timer(id, loop_chan) { + uv_timer(id, loop) { let msg = msg_timer_start(id, timeout, repeat, timer_cb); + let loop_chan = get_loop_chan_from_uv_loop(loop); comm::send(loop_chan, msg); } _ { @@ -367,7 +384,8 @@ fn timer_start(the_timer: uv_handle, timeout: u32, repeat:u32, fn timer_stop(the_timer: uv_handle, after_cb: fn~(uv_handle)) { alt the_timer { - uv_timer(id, loop_chan) { + uv_timer(id, loop) { + let loop_chan = get_loop_chan_from_uv_loop(loop); let msg = msg_timer_stop(id, after_cb); comm::send(loop_chan, msg); } @@ -397,15 +415,16 @@ fn get_handle_id_from(buf: *u8) -> [u8] unsafe { } fn get_loop_chan_from_data(data: *uv_loop_data) - -> uv_loop unsafe { + -> comm::chan unsafe { ret (*data).rust_loop_chan; } fn get_loop_chan_from_handle(handle: uv_handle) - -> uv_loop { + -> comm::chan { alt handle { uv_async(id,loop) | uv_timer(id,loop) { - ret loop; + let loop_chan = get_loop_chan_from_uv_loop(loop); + ret loop_chan; } _ { fail "unknown form of uv_handle for get_loop_chan_from " @@ -414,6 +433,21 @@ fn get_loop_chan_from_handle(handle: uv_handle) } } +fn get_loop_ptr_from_uv_loop(loop: uv_loop) -> *ctypes::void { + alt loop { + uv_loop_new(loop_chan, loop_ptr) { + ret loop_ptr; + } + } +} +fn get_loop_chan_from_uv_loop(loop: uv_loop) -> comm::chan { + alt loop { + uv_loop_new(loop_chan, loop_ptr) { + ret loop_chan; + } + } +} + fn get_id_from_handle(handle: uv_handle) -> [u8] { alt handle { uv_async(id,loop) | uv_timer(id,loop) { @@ -548,41 +582,44 @@ crust fn process_close_timer( #[test] fn test_uv_new_loop_no_handles() { let test_loop = uv::loop_new(); - run(test_loop); // this should return immediately + uv::run(test_loop); // this should return immediately // since there aren't any handles.. + uv::loop_delete(test_loop); } #[test] fn test_uv_simple_async() { - let test_loop = loop_new(); + let test_loop = uv::loop_new(); let exit_port = comm::port::(); let exit_chan = comm::chan::(exit_port); - async_init(test_loop, {|new_async| - close(new_async) {|| + uv::async_init(test_loop, {|new_async| + uv::close(new_async) {|| comm::send(exit_chan, true); }; }, {|new_async| - async_send(new_async); + uv::async_send(new_async); }); - run(test_loop); + uv::run(test_loop); let result = comm::recv(exit_port); assert result; + uv::loop_delete(test_loop); } #[test] fn test_uv_timer() { - let test_loop = loop_new(); + let test_loop = uv::loop_new(); let exit_port = comm::port::(); let exit_chan = comm::chan::(exit_port); - timer_init(test_loop) {|new_timer| - timer_start(new_timer, 1u32, 0u32) {|started_timer| - timer_stop(started_timer) {|stopped_timer| - close(stopped_timer) {|| + uv::timer_init(test_loop) {|new_timer| + uv::timer_start(new_timer, 1u32, 0u32) {|started_timer| + uv::timer_stop(started_timer) {|stopped_timer| + uv::close(stopped_timer) {|| comm::send(exit_chan, true); }; }; }; }; - run(test_loop); + uv::run(test_loop); assert comm::recv(exit_port); -} \ No newline at end of file + uv::loop_delete(test_loop); +} diff --git a/src/rt/rust_uv.cpp b/src/rt/rust_uv.cpp index 4126896895e..096d40d2235 100644 --- a/src/rt/rust_uv.cpp +++ b/src/rt/rust_uv.cpp @@ -2,7 +2,8 @@ #include "uv.h" // crust fn pointers -typedef void (*crust_async_op_cb)(uv_loop_t* loop, void* data); +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); @@ -43,7 +44,7 @@ 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); + cb(handle->loop, loop_data, handle); } static void @@ -78,6 +79,11 @@ 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;