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().
This commit is contained in:
Jeff Olson 2012-02-25 22:08:52 -08:00 committed by Brian Anderson
parent 0b3a06ab2c
commit b4c88cdcec
2 changed files with 75 additions and 32 deletions

View File

@ -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<uv_msg>
};
type uv_loop = comm::chan<uv_msg>;
enum uv_loop {
uv_loop_new(comm::chan<uv_msg>, *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::<uv_msg>(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::<bool>();
let end_chan = comm::chan::<bool>(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<uv_msg> unsafe {
ret (*data).rust_loop_chan;
}
fn get_loop_chan_from_handle(handle: uv_handle)
-> uv_loop {
-> comm::chan<uv_msg> {
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<uv_msg> {
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::<bool>();
let exit_chan = comm::chan::<bool>(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::<bool>();
let exit_chan = comm::chan::<bool>(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);
}
uv::loop_delete(test_loop);
}

View File

@ -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;