about summary refs log tree commit diff
path: root/src/libstd/timer.rs
diff options
context:
space:
mode:
authorJeff Olson <olson.jeffery@gmail.com>2012-04-20 09:08:02 -0700
committerBrian Anderson <banderson@mozilla.com>2012-04-20 15:23:23 -0700
commit707391edbce75b717779d074bf5f5e4b57901e98 (patch)
tree3fba98740ed8549cb1d165a5b5448e405d164e68 /src/libstd/timer.rs
parent7ac8c3081c5d4d7b1c79942e426770c1c3e1c0b3 (diff)
downloadrust-707391edbce75b717779d074bf5f5e4b57901e98.tar.gz
rust-707391edbce75b717779d074bf5f5e4b57901e98.zip
std: add timer::recv_timeout() and whitespace cleanup
Diffstat (limited to 'src/libstd/timer.rs')
-rw-r--r--src/libstd/timer.rs80
1 files changed, 75 insertions, 5 deletions
diff --git a/src/libstd/timer.rs b/src/libstd/timer.rs
index c8243ae8cf1..b1d01424fe3 100644
--- a/src/libstd/timer.rs
+++ b/src/libstd/timer.rs
@@ -3,7 +3,7 @@ Utilities that leverage libuv's `uv_timer_*` API
 "];
 
 import uv = uv;
-export delayed_send, sleep;
+export delayed_send, sleep, recv_timeout;
 
 #[doc = "
 Wait for timeout period then send provided value over a channel
@@ -16,9 +16,9 @@ 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`
+* 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() {||
@@ -80,6 +80,39 @@ fn sleep(msecs: uint) {
     comm::recv(exit_po);
 }
 
+#[doc = "
+Receive on a port for (up to) a specified time, then return an `option<T>`
+
+This call will block to receive on the provided port for up to the specified
+timeout. Depending on whether the provided port receives in that time period,
+`recv_timeout` will return an `option<T>` representing the result.
+
+# Arguments
+
+* msecs - an mount of time, in milliseconds, to wait to receive
+* wait_port - a `comm::port<T>` to receive on
+
+# Returns
+
+An `option<T>` representing the outcome of the call. If the call `recv`'d on
+the provided port in the allotted timeout period, then the result will be a
+`some(T)`. If not, then `none` will be returned.
+"]
+fn recv_timeout<T: send>(msecs: uint, wait_po: comm::port<T>) -> option<T> {
+    let timeout_po = comm::port::<()>();
+    let timeout_ch = comm::chan(timeout_po);
+    delayed_send(msecs, timeout_ch, ());
+    either::either(
+        {|left_val|
+            log(debug, #fmt("recv_time .. left_val %?",
+                           left_val));
+            none
+        }, {|right_val|
+            some(right_val)
+        }, comm::select2(timeout_po, wait_po)
+    )
+}
+
 // INTERNAL API
 crust fn delayed_send_cb(handle: *uv::ll::uv_timer_t,
                                 status: libc::c_int) unsafe {
@@ -108,6 +141,43 @@ crust fn delayed_send_close_cb(handle: *uv::ll::uv_timer_t) unsafe {
 mod test {
     #[test]
     fn test_timer_simple_sleep_test() {
-        sleep(2000u);
+        sleep(1u);
+    }
+
+    #[test]
+    fn test_timer_recv_timeout_before_time_passes() {
+        let expected = rand::rng().gen_str(16u);
+        let test_po = comm::port::<str>();
+        let test_ch = comm::chan(test_po);
+
+        task::spawn() {||
+            delayed_send(1u, test_ch, expected);
+        };
+
+        let actual = alt recv_timeout(1000u, test_po) {
+          some(val) { val }
+          _ { fail "test_timer_recv_timeout_before_time_passes:"+
+                    " didn't receive result before timeout"; }
+        };
+        assert actual == expected;
+    }
+
+    #[test]
+    fn test_timer_recv_timeout_after_time_passes() {
+        let expected = rand::rng().gen_str(16u);
+        let fail_msg = rand::rng().gen_str(16u);
+        let test_po = comm::port::<str>();
+        let test_ch = comm::chan(test_po);
+
+        task::spawn() {||
+            delayed_send(1000u, test_ch, expected);
+        };
+
+        let actual = alt recv_timeout(1u, test_po) {
+          none { fail_msg }
+          _ { fail "test_timer_recv_timeout_before_time_passes:"+
+                    " didn't receive result before timeout"; }
+        };
+        assert actual == fail_msg;
     }
 }