std: Clean up uv_global_loop

This commit is contained in:
Brian Anderson 2012-05-24 21:38:48 -07:00
parent 26ed1e91c8
commit 2a82a9907f
2 changed files with 84 additions and 82 deletions

View File

@ -2,11 +2,15 @@
A process-wide libuv event loop for library use.
"];
export get, get_monitor_task_gl;
import ll = uv_ll;
import hl = uv_hl;
import get_gl = get;
export get, get_monitor_task_gl;
import task::{spawn_sched, single_threaded};
import priv::{chan_from_global_ptr, weaken_task};
import comm::{port, chan, methods, select2, listen};
import either::{left, right};
native mod rustrt {
fn rust_uv_get_kernel_global_chan_ptr() -> *libc::uintptr_t;
@ -29,114 +33,108 @@ fn get() -> hl::high_level_loop {
}
#[doc(hidden)]
fn get_monitor_task_gl() -> hl::high_level_loop {
let monitor_loop_chan_ptr =
rustrt::rust_uv_get_kernel_global_chan_ptr();
log(debug, #fmt("ENTERING global_loop::get() loop chan: %?",
monitor_loop_chan_ptr));
fn get_monitor_task_gl() -> hl::high_level_loop unsafe {
let monitor_loop_chan_ptr = rustrt::rust_uv_get_kernel_global_chan_ptr();
#debug("ENTERING global_loop::get() loop chan: %?",
monitor_loop_chan_ptr);
let builder_fn = {||
let builder = task::builder();
let opts = {
task::set_opts(builder, {
supervise: false,
notify_chan: none,
sched:
some({mode: task::manual_threads(1u),
native_stack_size: none })
};
task::set_opts(builder, opts);
sched: some({
mode: single_threaded,
native_stack_size: none
})
with task::get_opts(builder)
});
builder
};
unsafe {
log(debug, "before priv::chan_from_global_ptr");
type hl_loop_req_ch = comm::chan<hl::high_level_loop>;
let msg_ch = priv::chan_from_global_ptr::<hl_loop_req_ch>(
monitor_loop_chan_ptr,
builder_fn) {|msg_po|
log(debug, "global monitor task starting");
priv::weaken_task() {|weak_exit_po|
log(debug, "global monitor task is now weak");
let hl_loop_data = spawn_high_level_loop();
let hl_loop = alt hl_loop_data {
(async, msg_ch) {
hl::high_level_loop({async_handle:async, op_chan:msg_ch})
#debug("before priv::chan_from_global_ptr");
type monchan = chan<hl::high_level_loop>;
let monitor_ch = chan_from_global_ptr::<monchan>(monitor_loop_chan_ptr,
builder_fn) {|msg_po|
#debug("global monitor task starting");
// As a weak task the runtime will notify us when to exit
weaken_task() {|weak_exit_po|
#debug("global monitor task is now weak");
let hl_loop = spawn_high_level_loop();
loop {
#debug("in outer_loop...");
alt select2(weak_exit_po, msg_po) {
left(weak_exit) {
// all normal tasks have ended, tell the
// libuv loop to tear_down, then exit
#debug("weak_exit_po recv'd msg: %?", weak_exit);
hl::exit(hl_loop);
break;
}
right(fetch_ch) {
#debug("hl_loop req recv'd: %?", fetch_ch);
fetch_ch.send(hl_loop);
}
};
loop {
log(debug, "in outer_loop...");
let continue = either::either(
{|weak_exit|
// all normal tasks have ended, tell the
// libuv loop to tear_down, then exit
log(debug, #fmt("weak_exit_po recv'd msg: %?",
weak_exit));
let ( a, loop_msg_ch )= hl_loop_data;
comm::send(loop_msg_ch, hl::teardown_loop);
ll::async_send(a);
false
}, {|fetch_ch|
log(debug, #fmt("hl_loop req recv'd: %?",
fetch_ch));
comm::send(fetch_ch, copy(hl_loop));
true
}, comm::select2(weak_exit_po, msg_po));
if !continue { break; }
}
log(debug, "global monitor task is leaving weakend state");
};
log(debug, "global monitor task exiting");
}
#debug("global monitor task is leaving weakend state");
};
// once we have a chan to the monitor loop, we ask it for
// the libuv loop's async handle
let fetch_po = comm::port::<hl::high_level_loop>();
let fetch_ch = comm::chan(fetch_po);
comm::send(msg_ch, fetch_ch);
comm::recv(fetch_po)
#debug("global monitor task exiting");
};
// once we have a chan to the monitor loop, we ask it for
// the libuv loop's async handle
listen { |fetch_ch|
monitor_ch.send(fetch_ch);
fetch_ch.recv()
}
}
unsafe fn spawn_high_level_loop() -> (*ll::uv_async_t,
comm::chan<hl::high_level_msg>){
let exit_po = comm::port::<(*ll::uv_async_t,
comm::chan<hl::high_level_msg>)>();
let exit_ch = comm::chan(exit_po);
fn spawn_high_level_loop() -> hl::high_level_loop unsafe {
let exit_po = port::<hl::high_level_loop>();
let exit_ch = exit_po.chan();
task::spawn_sched(task::manual_threads(1u)) {||
log(debug, "entering global libuv task");
let loop_ptr = ll::loop_new();
priv::weaken_task() {|weak_exit_po|
log(debug, #fmt("global libuv task is now weak %?",
weak_exit_po));
let loop_msg_po = comm::port::<hl::high_level_msg>();
let loop_msg_ch = comm::chan(loop_msg_po);
spawn_sched(single_threaded) {||
#debug("entering global libuv task");
weaken_task() {|weak_exit_po|
#debug("global libuv task is now weak %?", weak_exit_po);
let loop_ptr = ll::loop_new();
let loop_msg_po = port::<hl::high_level_msg>();
let loop_msg_ch = loop_msg_po.chan();
hl::run_high_level_loop(
loop_ptr,
loop_msg_po,
// before_run
{|async_handle|
log(debug,#fmt("global libuv: before_run %?",
async_handle));
let out_data = (async_handle, loop_msg_ch);
comm::send(exit_ch, out_data);
#debug("global libuv: before_run %?", async_handle);
let hll = hl::high_level_loop({
async_handle: async_handle,
op_chan: loop_msg_ch
});
exit_ch.send(hll);
},
// before_msg_process
{|async_handle, loop_active|
log(debug,#fmt("global libuv: before_msg_drain %? %?",
async_handle, loop_active));
#debug("global libuv: before_msg_drain %? %?",
async_handle, loop_active);
true
},
// before_tear_down
{|async_handle|
log(debug,#fmt("libuv task: before_tear_down %?",
async_handle));
#debug("libuv task: before_tear_down %?",
async_handle);
}
);
log(debug, "global libuv task is leaving weakened state");
ll::loop_delete(loop_ptr);
#debug("global libuv task is leaving weakened state");
};
ll::loop_delete(loop_ptr);
log(debug, "global libuv task exiting");
#debug("global libuv task exiting");
};
comm::recv(exit_po)
exit_po.recv()
}
#[cfg(test)]

View File

@ -7,7 +7,7 @@ libuv functionality.
"];
export high_level_loop, high_level_msg;
export run_high_level_loop, interact;
export run_high_level_loop, interact, exit;
import libc::c_void;
import ptr::addr_of;
@ -119,6 +119,10 @@ unsafe fn interact(hl_loop: high_level_loop,
send_high_level_msg(hl_loop, interaction(cb));
}
fn exit(hl_loop: high_level_loop) unsafe {
send_high_level_msg(hl_loop, teardown_loop);
}
// INTERNAL API
// data that lives for the lifetime of the high-evel oo