std: add std::timer and timer::delayed_send and timer::sleep
.. leveraging std::uv, we have: timer::delayed_send - send a value over a provided channel after the timeout has passed timer::sleep - block the current task for the specified period both of these fns (and everything that goes in timer.rs) leverage the uv_timer_* API
This commit is contained in:
parent
a1c43cc7c9
commit
7ac8c3081c
@ -14,7 +14,7 @@ use core(vers = "0.2");
|
|||||||
import core::*;
|
import core::*;
|
||||||
|
|
||||||
export net, uv;
|
export net, uv;
|
||||||
export c_vec, util;
|
export c_vec, util, timer;
|
||||||
export bitv, deque, fun_treemap, list, map, smallintmap, sort, treemap, ufind;
|
export bitv, deque, fun_treemap, list, map, smallintmap, sort, treemap, ufind;
|
||||||
export rope, arena;
|
export rope, arena;
|
||||||
export ebml, dbg, getopts, json, rand, sha1, term, time, prettyprint;
|
export ebml, dbg, getopts, json, rand, sha1, term, time, prettyprint;
|
||||||
@ -35,6 +35,7 @@ mod uv_global_loop;
|
|||||||
|
|
||||||
mod c_vec;
|
mod c_vec;
|
||||||
mod util;
|
mod util;
|
||||||
|
mod timer;
|
||||||
|
|
||||||
|
|
||||||
// Collections
|
// Collections
|
||||||
|
113
src/libstd/timer.rs
Normal file
113
src/libstd/timer.rs
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
#[doc ="
|
||||||
|
Utilities that leverage libuv's `uv_timer_*` API
|
||||||
|
"];
|
||||||
|
|
||||||
|
import uv = uv;
|
||||||
|
export delayed_send, sleep;
|
||||||
|
|
||||||
|
#[doc = "
|
||||||
|
Wait for timeout period then send provided value over a channel
|
||||||
|
|
||||||
|
This call returns immediately. Useful as the building block for a number
|
||||||
|
of higher-level timer functions.
|
||||||
|
|
||||||
|
Is not guaranteed to wait for exactly the specified time, but will wait
|
||||||
|
for *at least* that period of time.
|
||||||
|
|
||||||
|
# Arguments
|
||||||
|
|
||||||
|
msecs - a timeout period, in milliseconds, to wait
|
||||||
|
ch - a channel of type T to send a `val` on
|
||||||
|
val - a value of type T to send over the provided `ch`
|
||||||
|
"]
|
||||||
|
fn delayed_send<T: send>(msecs: uint, ch: comm::chan<T>, val: T) {
|
||||||
|
task::spawn() {||
|
||||||
|
unsafe {
|
||||||
|
let timer_done_po = comm::port::<()>();
|
||||||
|
let timer_done_ch = comm::chan(timer_done_po);
|
||||||
|
let timer_done_ch_ptr = ptr::addr_of(timer_done_ch);
|
||||||
|
let timer = uv::ll::timer_t();
|
||||||
|
let timer_ptr = ptr::addr_of(timer);
|
||||||
|
let hl_loop = uv::global_loop::get();
|
||||||
|
uv::hl::interact(hl_loop) {|loop_ptr|
|
||||||
|
uv::hl::ref(hl_loop, timer_ptr);
|
||||||
|
let init_result = uv::ll::timer_init(loop_ptr, timer_ptr);
|
||||||
|
if (init_result == 0i32) {
|
||||||
|
let start_result = uv::ll::timer_start(
|
||||||
|
timer_ptr, delayed_send_cb, msecs, 0u);
|
||||||
|
if (start_result == 0i32) {
|
||||||
|
uv::ll::set_data_for_uv_handle(
|
||||||
|
timer_ptr,
|
||||||
|
timer_done_ch_ptr as *libc::c_void);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let error_msg = uv::ll::get_last_err_info(loop_ptr);
|
||||||
|
fail "timer::delayed_send() start failed: "+error_msg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let error_msg = uv::ll::get_last_err_info(loop_ptr);
|
||||||
|
fail "timer::delayed_send() init failed: "+error_msg;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// delayed_send_cb has been processed by libuv
|
||||||
|
comm::recv(timer_done_po);
|
||||||
|
// notify the caller immediately
|
||||||
|
comm::send(ch, copy(val));
|
||||||
|
// then clean up our handle
|
||||||
|
uv::hl::unref_and_close(hl_loop, timer_ptr,
|
||||||
|
delayed_send_close_cb);
|
||||||
|
// uv_close for this timer has been processed
|
||||||
|
comm::recv(timer_done_po);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc = "
|
||||||
|
Blocks the current task for (at least) the specified time period.
|
||||||
|
|
||||||
|
Is not guaranteed to sleep for exactly the specified time, but will sleep
|
||||||
|
for *at least* that period of time.
|
||||||
|
|
||||||
|
# Arguments
|
||||||
|
|
||||||
|
* msecs - an amount of time, in milliseconds, for the current task to block
|
||||||
|
"]
|
||||||
|
fn sleep(msecs: uint) {
|
||||||
|
let exit_po = comm::port::<()>();
|
||||||
|
let exit_ch = comm::chan(exit_po);
|
||||||
|
delayed_send(msecs, exit_ch, ());
|
||||||
|
comm::recv(exit_po);
|
||||||
|
}
|
||||||
|
|
||||||
|
// INTERNAL API
|
||||||
|
crust fn delayed_send_cb(handle: *uv::ll::uv_timer_t,
|
||||||
|
status: libc::c_int) unsafe {
|
||||||
|
log(debug, #fmt("delayed_send_cb handle %? status %?", handle, status));
|
||||||
|
let timer_done_ch =
|
||||||
|
*(uv::ll::get_data_for_uv_handle(handle) as *comm::chan<()>);
|
||||||
|
let stop_result = uv::ll::timer_stop(handle);
|
||||||
|
if (stop_result == 0i32) {
|
||||||
|
comm::send(timer_done_ch, ());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let loop_ptr = uv::ll::get_loop_for_uv_handle(handle);
|
||||||
|
let error_msg = uv::ll::get_last_err_info(loop_ptr);
|
||||||
|
fail "timer::sleep() init failed: "+error_msg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
crust fn delayed_send_close_cb(handle: *uv::ll::uv_timer_t) unsafe {
|
||||||
|
log(debug, #fmt("delayed_send_close_cb handle %?", handle));
|
||||||
|
let timer_done_ch =
|
||||||
|
*(uv::ll::get_data_for_uv_handle(handle) as *comm::chan<()>);
|
||||||
|
comm::send(timer_done_ch, ());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
#[test]
|
||||||
|
fn test_timer_simple_sleep_test() {
|
||||||
|
sleep(2000u);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user