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:
parent
0b3a06ab2c
commit
b4c88cdcec
|
@ -1,5 +1,6 @@
|
||||||
export loop_new, run, close, run_in_bg, async_init, async_send,
|
export loop_new, loop_delete, run, close, run_in_bg;
|
||||||
timer_init, timer_start, timer_stop;
|
export async_init, async_send;
|
||||||
|
export timer_init, timer_start, timer_stop;
|
||||||
|
|
||||||
// these are processed solely in the
|
// these are processed solely in the
|
||||||
// process_operation() crust fn below
|
// process_operation() crust fn below
|
||||||
|
@ -44,11 +45,14 @@ type uv_loop_data = {
|
||||||
rust_loop_chan: comm::chan<uv_msg>
|
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]
|
#[nolink]
|
||||||
native mod rustrt {
|
native mod rustrt {
|
||||||
fn rust_uv_loop_new() -> *ctypes::void;
|
fn rust_uv_loop_new() -> *ctypes::void;
|
||||||
|
fn rust_uv_loop_delete(loop: *ctypes::void);
|
||||||
fn rust_uv_loop_set_data(
|
fn rust_uv_loop_set_data(
|
||||||
loop: *ctypes::void,
|
loop: *ctypes::void,
|
||||||
data: *uv_loop_data);
|
data: *uv_loop_data);
|
||||||
|
@ -103,7 +107,8 @@ fn loop_new() -> uv_loop unsafe {
|
||||||
let rust_loop_chan =
|
let rust_loop_chan =
|
||||||
comm::chan::<uv_msg>(rust_loop_port);
|
comm::chan::<uv_msg>(rust_loop_port);
|
||||||
// let the task-spawner return
|
// 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
|
// create our "special" async handle that will
|
||||||
// allow all operations against libuv to be
|
// allow all operations against libuv to be
|
||||||
|
@ -225,7 +230,7 @@ fn loop_new() -> uv_loop unsafe {
|
||||||
handles.insert(id, async_handle);
|
handles.insert(id, async_handle);
|
||||||
let after_cb = after_cbs.get(id);
|
let after_cb = after_cbs.get(id);
|
||||||
after_cbs.remove(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));
|
id_to_handle.insert(id, copy(async));
|
||||||
task::spawn {||
|
task::spawn {||
|
||||||
after_cb(async);
|
after_cb(async);
|
||||||
|
@ -239,7 +244,8 @@ fn loop_new() -> uv_loop unsafe {
|
||||||
uv_async_send(id) {
|
uv_async_send(id) {
|
||||||
let async_cb = async_cbs.get(id);
|
let async_cb = async_cbs.get(id);
|
||||||
task::spawn {||
|
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);
|
handles.insert(id, handle);
|
||||||
let after_cb = after_cbs.get(id);
|
let after_cb = after_cbs.get(id);
|
||||||
after_cbs.remove(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));
|
id_to_handle.insert(id, copy(new_timer));
|
||||||
task::spawn {||
|
task::spawn {||
|
||||||
after_cb(new_timer);
|
after_cb(new_timer);
|
||||||
|
@ -310,15 +316,22 @@ fn loop_new() -> uv_loop unsafe {
|
||||||
ret comm::recv(ret_recv_port);
|
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) {
|
fn run(loop: uv_loop) {
|
||||||
let end_port = comm::port::<bool>();
|
let end_port = comm::port::<bool>();
|
||||||
let end_chan = comm::chan::<bool>(end_port);
|
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);
|
comm::recv(end_port);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_in_bg(loop: uv_loop) {
|
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 (
|
fn async_init (
|
||||||
|
@ -326,13 +339,15 @@ fn async_init (
|
||||||
async_cb: fn~(uv_handle),
|
async_cb: fn~(uv_handle),
|
||||||
after_cb: fn~(uv_handle)) {
|
after_cb: fn~(uv_handle)) {
|
||||||
let msg = msg_async_init(async_cb, after_cb);
|
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) {
|
fn async_send(async: uv_handle) {
|
||||||
alt async {
|
alt async {
|
||||||
uv_async(id, loop) {
|
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" +
|
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)) {
|
fn timer_init(loop: uv_loop, after_cb: fn~(uv_handle)) {
|
||||||
let msg = msg_timer_init(after_cb);
|
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,
|
fn timer_start(the_timer: uv_handle, timeout: u32, repeat:u32,
|
||||||
timer_cb: fn~(uv_handle)) {
|
timer_cb: fn~(uv_handle)) {
|
||||||
alt the_timer {
|
alt the_timer {
|
||||||
uv_timer(id, loop_chan) {
|
uv_timer(id, loop) {
|
||||||
let msg = msg_timer_start(id, timeout, repeat, timer_cb);
|
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);
|
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)) {
|
fn timer_stop(the_timer: uv_handle, after_cb: fn~(uv_handle)) {
|
||||||
alt the_timer {
|
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);
|
let msg = msg_timer_stop(id, after_cb);
|
||||||
comm::send(loop_chan, msg);
|
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)
|
fn get_loop_chan_from_data(data: *uv_loop_data)
|
||||||
-> uv_loop unsafe {
|
-> comm::chan<uv_msg> unsafe {
|
||||||
ret (*data).rust_loop_chan;
|
ret (*data).rust_loop_chan;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_loop_chan_from_handle(handle: uv_handle)
|
fn get_loop_chan_from_handle(handle: uv_handle)
|
||||||
-> uv_loop {
|
-> comm::chan<uv_msg> {
|
||||||
alt handle {
|
alt handle {
|
||||||
uv_async(id,loop) | uv_timer(id,loop) {
|
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 "
|
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] {
|
fn get_id_from_handle(handle: uv_handle) -> [u8] {
|
||||||
alt handle {
|
alt handle {
|
||||||
uv_async(id,loop) | uv_timer(id,loop) {
|
uv_async(id,loop) | uv_timer(id,loop) {
|
||||||
|
@ -548,41 +582,44 @@ crust fn process_close_timer(
|
||||||
#[test]
|
#[test]
|
||||||
fn test_uv_new_loop_no_handles() {
|
fn test_uv_new_loop_no_handles() {
|
||||||
let test_loop = uv::loop_new();
|
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..
|
// since there aren't any handles..
|
||||||
|
uv::loop_delete(test_loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_uv_simple_async() {
|
fn test_uv_simple_async() {
|
||||||
let test_loop = loop_new();
|
let test_loop = uv::loop_new();
|
||||||
let exit_port = comm::port::<bool>();
|
let exit_port = comm::port::<bool>();
|
||||||
let exit_chan = comm::chan::<bool>(exit_port);
|
let exit_chan = comm::chan::<bool>(exit_port);
|
||||||
async_init(test_loop, {|new_async|
|
uv::async_init(test_loop, {|new_async|
|
||||||
close(new_async) {||
|
uv::close(new_async) {||
|
||||||
comm::send(exit_chan, true);
|
comm::send(exit_chan, true);
|
||||||
};
|
};
|
||||||
}, {|new_async|
|
}, {|new_async|
|
||||||
async_send(new_async);
|
uv::async_send(new_async);
|
||||||
});
|
});
|
||||||
run(test_loop);
|
uv::run(test_loop);
|
||||||
let result = comm::recv(exit_port);
|
let result = comm::recv(exit_port);
|
||||||
assert result;
|
assert result;
|
||||||
|
uv::loop_delete(test_loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_uv_timer() {
|
fn test_uv_timer() {
|
||||||
let test_loop = loop_new();
|
let test_loop = uv::loop_new();
|
||||||
let exit_port = comm::port::<bool>();
|
let exit_port = comm::port::<bool>();
|
||||||
let exit_chan = comm::chan::<bool>(exit_port);
|
let exit_chan = comm::chan::<bool>(exit_port);
|
||||||
timer_init(test_loop) {|new_timer|
|
uv::timer_init(test_loop) {|new_timer|
|
||||||
timer_start(new_timer, 1u32, 0u32) {|started_timer|
|
uv::timer_start(new_timer, 1u32, 0u32) {|started_timer|
|
||||||
timer_stop(started_timer) {|stopped_timer|
|
uv::timer_stop(started_timer) {|stopped_timer|
|
||||||
close(stopped_timer) {||
|
uv::close(stopped_timer) {||
|
||||||
comm::send(exit_chan, true);
|
comm::send(exit_chan, true);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
run(test_loop);
|
uv::run(test_loop);
|
||||||
assert comm::recv(exit_port);
|
assert comm::recv(exit_port);
|
||||||
}
|
uv::loop_delete(test_loop);
|
||||||
|
}
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
#include "uv.h"
|
#include "uv.h"
|
||||||
|
|
||||||
// crust fn pointers
|
// 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_simple_cb)(uint8_t* id_buf, void* loop_data);
|
||||||
typedef void (*crust_close_cb)(uint8_t* id_buf, void* handle,
|
typedef void (*crust_close_cb)(uint8_t* id_buf, void* handle,
|
||||||
void* data);
|
void* data);
|
||||||
|
@ -43,7 +44,7 @@ static void
|
||||||
native_crust_async_op_cb(uv_async_t* handle, int status) {
|
native_crust_async_op_cb(uv_async_t* handle, int status) {
|
||||||
crust_async_op_cb cb = (crust_async_op_cb)handle->data;
|
crust_async_op_cb cb = (crust_async_op_cb)handle->data;
|
||||||
void* loop_data = handle->loop->data;
|
void* loop_data = handle->loop->data;
|
||||||
cb(handle->loop, loop_data);
|
cb(handle->loop, loop_data, handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -78,6 +79,11 @@ rust_uv_loop_new() {
|
||||||
return (void*)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
|
extern "C" void
|
||||||
rust_uv_loop_set_data(uv_loop_t* loop, void* data) {
|
rust_uv_loop_set_data(uv_loop_t* loop, void* data) {
|
||||||
loop->data = data;
|
loop->data = data;
|
||||||
|
|
Loading…
Reference in New Issue