about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBrian Anderson <banderson@mozilla.com>2014-07-30 20:07:41 -0700
committerBrian Anderson <banderson@mozilla.com>2014-08-13 11:31:47 -0700
commit63cd4acf535f8df177459559fe2d7e6ab390c6d8 (patch)
tree4f10ee436e87176f9141071d2a7a13d5ee499ba8
parent734834c7d6e4862c8348a8c9660bb338773047ca (diff)
downloadrust-63cd4acf535f8df177459559fe2d7e6ab390c6d8.tar.gz
rust-63cd4acf535f8df177459559fe2d7e6ab390c6d8.zip
std: Clarify what timers do with zero and negative durations
Add tests. Also fix a bunch of broken time tests.
-rw-r--r--src/libstd/io/process.rs2
-rw-r--r--src/libstd/io/signal.rs7
-rw-r--r--src/libstd/io/test.rs1
-rw-r--r--src/libstd/io/timer.rs89
-rw-r--r--src/libstd/task.rs3
-rw-r--r--src/libstd/time.rs40
6 files changed, 111 insertions, 31 deletions
diff --git a/src/libstd/io/process.rs b/src/libstd/io/process.rs
index 41a621f6edf..3dd4343c5f4 100644
--- a/src/libstd/io/process.rs
+++ b/src/libstd/io/process.rs
@@ -976,7 +976,7 @@ mod tests {
                 assert!(!p.wait().unwrap().success());
                 return
             }
-            timer::sleep_ms(100);
+            timer::sleep(Duration::milliseconds(100));
         }
         fail!("never saw the child go away");
     })
diff --git a/src/libstd/io/signal.rs b/src/libstd/io/signal.rs
index 4ea91131f17..10739c70143 100644
--- a/src/libstd/io/signal.rs
+++ b/src/libstd/io/signal.rs
@@ -167,6 +167,7 @@ mod test_unix {
     use comm::Empty;
     use io::timer;
     use super::{Listener, Interrupt};
+    use time::Duration;
 
     fn sigint() {
         unsafe {
@@ -179,7 +180,7 @@ mod test_unix {
         let mut signal = Listener::new();
         signal.register(Interrupt).unwrap();
         sigint();
-        timer::sleep_ms(10);
+        timer::sleep(Duration::milliseconds(10));
         match signal.rx.recv() {
             Interrupt => (),
             s => fail!("Expected Interrupt, got {:?}", s),
@@ -193,7 +194,7 @@ mod test_unix {
         s1.register(Interrupt).unwrap();
         s2.register(Interrupt).unwrap();
         sigint();
-        timer::sleep_ms(10);
+        timer::sleep(Duration::milliseconds(10));
         match s1.rx.recv() {
             Interrupt => (),
             s => fail!("Expected Interrupt, got {:?}", s),
@@ -212,7 +213,7 @@ mod test_unix {
         s2.register(Interrupt).unwrap();
         s2.unregister(Interrupt);
         sigint();
-        timer::sleep_ms(10);
+        timer::sleep(Duration::milliseconds(10));
         assert_eq!(s2.rx.try_recv(), Err(Empty));
     }
 }
diff --git a/src/libstd/io/test.rs b/src/libstd/io/test.rs
index 331cfa1a59e..079a9aef648 100644
--- a/src/libstd/io/test.rs
+++ b/src/libstd/io/test.rs
@@ -39,6 +39,7 @@ macro_rules! iotest (
             use io::process::*;
             use rt::running_on_valgrind;
             use str;
+            use time::Duration;
 
             fn f() $b
 
diff --git a/src/libstd/io/timer.rs b/src/libstd/io/timer.rs
index d9f35ed73e0..0d3f932f429 100644
--- a/src/libstd/io/timer.rs
+++ b/src/libstd/io/timer.rs
@@ -17,6 +17,8 @@ and create receivers which will receive notifications after a period of time.
 
 */
 
+// FIXME: These functions take Durations but only pass ms to the backend impls.
+
 use comm::{Receiver, Sender, channel};
 use time::Duration;
 use io::{IoResult, IoError};
@@ -71,13 +73,15 @@ pub struct Timer {
 struct TimerCallback { tx: Sender<()> }
 
 fn in_ms(d: Duration) -> u64 {
-    // FIXME: Do we really want to fail on negative duration?
     let ms = d.num_milliseconds();
-    if ms < 0 { fail!("negative duration") }
+    if ms < 0 { return 0 };
     return ms as u64;
 }
 
 /// Sleep the current task for the specified duration.
+///
+/// When provided a zero or negative `duration`, the function will
+/// return immediately.
 pub fn sleep(duration: Duration) {
     let timer = Timer::new();
     let mut timer = timer.ok().expect("timer::sleep: could not create a Timer");
@@ -99,8 +103,14 @@ impl Timer {
     ///
     /// Note that this function will cause any other receivers for this timer to
     /// be invalidated (the other end will be closed).
+    ///
+    /// When provided a zero or negative `duration`, the function will
+    /// return immediately.
     pub fn sleep(&mut self, duration: Duration) {
-        self.obj.sleep(in_ms(duration));
+        // Short-circuit the timer backend for 0 duration
+        let ms = in_ms(duration);
+        if ms == 0 { return }
+        self.obj.sleep(ms);
     }
 
     /// Creates a oneshot receiver which will have a notification sent when
@@ -137,9 +147,17 @@ impl Timer {
     /// // The timer object was destroyed, so this will always fail:
     /// // five_ms.recv()
     /// ```
+    ///
+    /// When provided a zero or negative `duration`, the message will
+    /// be sent immediately.
     pub fn oneshot(&mut self, duration: Duration) -> Receiver<()> {
         let (tx, rx) = channel();
-        self.obj.oneshot(in_ms(duration), box TimerCallback { tx: tx });
+        // Short-circuit the timer backend for 0 duration
+        if in_ms(duration) != 0 {
+            self.obj.oneshot(in_ms(duration), box TimerCallback { tx: tx });
+        } else {
+            tx.send(());
+        }
         return rx
     }
 
@@ -185,9 +203,17 @@ impl Timer {
     /// // The timer object was destroyed, so this will always fail:
     /// // five_ms.recv()
     /// ```
+    ///
+    /// When provided a zero or negative `duration`, the messages will
+    /// be sent without delay.
     pub fn periodic(&mut self, duration: Duration) -> Receiver<()> {
+        let ms = in_ms(duration);
+        // FIXME: The backend implementations don't ever send a message
+        // if given a 0 ms duration. Temporarily using 1ms. It's
+        // not clear what use a 0ms period is anyway...
+        let ms = if ms == 0 { 1 } else { ms };
         let (tx, rx) = channel();
-        self.obj.period(in_ms(duration), box TimerCallback { tx: tx });
+        self.obj.period(ms, box TimerCallback { tx: tx });
         return rx
     }
 }
@@ -200,8 +226,6 @@ impl Callback for TimerCallback {
 
 #[cfg(test)]
 mod test {
-    use time::Duration;
-
     iotest!(fn test_io_timer_sleep_simple() {
         let mut timer = Timer::new().unwrap();
         timer.sleep(Duration::milliseconds(1));
@@ -214,20 +238,20 @@ mod test {
 
     iotest!(fn test_io_timer_sleep_oneshot_forget() {
         let mut timer = Timer::new().unwrap();
-        timer.oneshot(Duration::milliseconds(100000000000));
+        timer.oneshot(Duration::milliseconds(100000000));
     })
 
     iotest!(fn oneshot_twice() {
         let mut timer = Timer::new().unwrap();
         let rx1 = timer.oneshot(Duration::milliseconds(10000));
-        let rx = timer.oneshot(1);
+        let rx = timer.oneshot(Duration::milliseconds(1));
         rx.recv();
         assert_eq!(rx1.recv_opt(), Err(()));
     })
 
     iotest!(fn test_io_timer_oneshot_then_sleep() {
         let mut timer = Timer::new().unwrap();
-        let rx = timer.oneshot(Duration::milliseconds(100000000000));
+        let rx = timer.oneshot(Duration::milliseconds(100000000));
         timer.sleep(Duration::milliseconds(1)); // this should invalidate rx
 
         assert_eq!(rx.recv_opt(), Err(()));
@@ -243,7 +267,7 @@ mod test {
 
     iotest!(fn test_io_timer_sleep_periodic_forget() {
         let mut timer = Timer::new().unwrap();
-        timer.periodic(Duration::milliseconds(100000000000));
+        timer.periodic(Duration::milliseconds(100000000));
     })
 
     iotest!(fn test_io_timer_sleep_standalone() {
@@ -277,7 +301,7 @@ mod test {
         let rx = timer.periodic(Duration::milliseconds(1));
         rx.recv();
         rx.recv();
-        let rx2 = timer.periodic(Durtion::milliseconds(1));
+        let rx2 = timer.periodic(Duration::milliseconds(1));
         rx2.recv();
         rx2.recv();
     })
@@ -375,4 +399,45 @@ mod test {
         // callback do something terrible.
         timer2.sleep(Duration::milliseconds(2));
     })
+
+    iotest!(fn sleep_zero() {
+        let mut timer = Timer::new().unwrap();
+        timer.sleep(Duration::milliseconds(0));
+    })
+
+    iotest!(fn sleep_negative() {
+        let mut timer = Timer::new().unwrap();
+        timer.sleep(Duration::milliseconds(-1000000));
+    })
+
+    iotest!(fn oneshot_zero() {
+        let mut timer = Timer::new().unwrap();
+        let rx = timer.oneshot(Duration::milliseconds(0));
+        rx.recv();
+    })
+
+    iotest!(fn oneshot_negative() {
+        let mut timer = Timer::new().unwrap();
+        let rx = timer.oneshot(Duration::milliseconds(-1000000));
+        rx.recv();
+    })
+
+    iotest!(fn periodic_zero() {
+        let mut timer = Timer::new().unwrap();
+        let rx = timer.periodic(Duration::milliseconds(0));
+        rx.recv();
+        rx.recv();
+        rx.recv();
+        rx.recv();
+    })
+
+    iotest!(fn periodic_negative() {
+        let mut timer = Timer::new().unwrap();
+        let rx = timer.periodic(Duration::milliseconds(-1000000));
+        rx.recv();
+        rx.recv();
+        rx.recv();
+        rx.recv();
+    })
+
 }
diff --git a/src/libstd/task.rs b/src/libstd/task.rs
index 96036b54e36..9cace9c80ef 100644
--- a/src/libstd/task.rs
+++ b/src/libstd/task.rs
@@ -664,10 +664,11 @@ mod test {
 #[test]
 fn task_abort_no_kill_runtime() {
     use std::io::timer;
+    use time::Duration;
     use mem;
 
     let tb = TaskBuilder::new();
     let rx = tb.try_future(proc() {});
     mem::drop(rx);
-    timer::sleep_ms(1000);
+    timer::sleep(Duration::milliseconds(1000));
 }
diff --git a/src/libstd/time.rs b/src/libstd/time.rs
index 1025d5c06fc..5a374c37cd8 100644
--- a/src/libstd/time.rs
+++ b/src/libstd/time.rs
@@ -497,12 +497,16 @@ fn div_rem_64(this: i64, other: i64) -> (i64, i64) {
 #[cfg(test)]
 mod tests {
     use super::{Duration, MIN_DAYS, MAX_DAYS, MIN_DURATION, MAX_DURATION};
-    use std::{i32, i64};
+    use {i32, i64};
+    use num::{Zero, CheckedAdd, CheckedSub};
+    use option::{Some, None};
+    use to_string::ToString;
 
     #[test]
     fn test_duration() {
-        assert_eq!(Duration::zero(), Duration::zero());
-        assert!(Duration::zero() != Duration::seconds(1));
+        let d: Duration = Zero::zero();
+        assert_eq!(d, Zero::zero());
+        assert!(Duration::seconds(1) != Zero::zero());
         assert_eq!(Duration::seconds(1) + Duration::seconds(2), Duration::seconds(3));
         assert_eq!(Duration::seconds(86399) + Duration::seconds(4),
                    Duration::days(1) + Duration::seconds(3));
@@ -517,7 +521,8 @@ mod tests {
 
     #[test]
     fn test_duration_num_days() {
-        assert_eq!(Duration::zero().num_days(), 0);
+        let d: Duration = Zero::zero();
+        assert_eq!(d.num_days(), 0);
         assert_eq!(Duration::days(1).num_days(), 1);
         assert_eq!(Duration::days(-1).num_days(), -1);
         assert_eq!(Duration::seconds(86399).num_days(), 0);
@@ -534,7 +539,8 @@ mod tests {
 
     #[test]
     fn test_duration_num_seconds() {
-        assert_eq!(Duration::zero().num_seconds(), 0);
+        let d: Duration = Zero::zero();
+        assert_eq!(d.num_seconds(), 0);
         assert_eq!(Duration::seconds(1).num_seconds(), 1);
         assert_eq!(Duration::seconds(-1).num_seconds(), -1);
         assert_eq!(Duration::milliseconds(999).num_seconds(), 0);
@@ -551,7 +557,8 @@ mod tests {
 
     #[test]
     fn test_duration_num_milliseconds() {
-        assert_eq!(Duration::zero().num_milliseconds(), 0);
+        let d: Duration = Zero::zero();
+        assert_eq!(d.num_milliseconds(), 0);
         assert_eq!(Duration::milliseconds(1).num_milliseconds(), 1);
         assert_eq!(Duration::milliseconds(-1).num_milliseconds(), -1);
         assert_eq!(Duration::microseconds(999).num_milliseconds(), 0);
@@ -568,7 +575,8 @@ mod tests {
 
     #[test]
     fn test_duration_num_microseconds() {
-        assert_eq!(Duration::zero().num_microseconds(), Some(0));
+        let d: Duration = Zero::zero();
+        assert_eq!(d.num_microseconds(), Some(0));
         assert_eq!(Duration::microseconds(1).num_microseconds(), Some(1));
         assert_eq!(Duration::microseconds(-1).num_microseconds(), Some(-1));
         assert_eq!(Duration::nanoseconds(999).num_microseconds(), Some(0));
@@ -594,7 +602,8 @@ mod tests {
 
     #[test]
     fn test_duration_num_nanoseconds() {
-        assert_eq!(Duration::zero().num_nanoseconds(), Some(0));
+        let d: Duration = Zero::zero();
+        assert_eq!(d.num_nanoseconds(), Some(0));
         assert_eq!(Duration::nanoseconds(1).num_nanoseconds(), Some(1));
         assert_eq!(Duration::nanoseconds(-1).num_nanoseconds(), Some(-1));
         assert_eq!(Duration::new(1, 2, 3_004_005).num_nanoseconds(), Some(86402_003_004_005));
@@ -627,9 +636,10 @@ mod tests {
 
     #[test]
     fn test_duration_mul() {
-        assert_eq!(Duration::zero() * i32::MAX, Duration::zero());
-        assert_eq!(Duration::zero() * i32::MIN, Duration::zero());
-        assert_eq!(Duration::nanoseconds(1) * 0, Duration::zero());
+        let d: Duration = Zero::zero();
+        assert_eq!(d * i32::MAX, d);
+        assert_eq!(d * i32::MIN, d);
+        assert_eq!(Duration::nanoseconds(1) * 0, Zero::zero());
         assert_eq!(Duration::nanoseconds(1) * 1, Duration::nanoseconds(1));
         assert_eq!(Duration::nanoseconds(1) * 1_000_000_000, Duration::seconds(1));
         assert_eq!(Duration::nanoseconds(1) * -1_000_000_000, -Duration::seconds(1));
@@ -642,8 +652,9 @@ mod tests {
 
     #[test]
     fn test_duration_div() {
-        assert_eq!(Duration::zero() / i32::MAX, Duration::zero());
-        assert_eq!(Duration::zero() / i32::MIN, Duration::zero());
+        let d: Duration = Zero::zero();
+        assert_eq!(d / i32::MAX, d);
+        assert_eq!(d / i32::MIN, d);
         assert_eq!(Duration::nanoseconds(123_456_789) / 1, Duration::nanoseconds(123_456_789));
         assert_eq!(Duration::nanoseconds(123_456_789) / -1, -Duration::nanoseconds(123_456_789));
         assert_eq!(-Duration::nanoseconds(123_456_789) / -1, Duration::nanoseconds(123_456_789));
@@ -652,7 +663,8 @@ mod tests {
 
     #[test]
     fn test_duration_fmt() {
-        assert_eq!(Duration::zero().to_string(), "PT0S".to_string());
+        let d: Duration = Zero::zero();
+        assert_eq!(d.to_string(), "PT0S".to_string());
         assert_eq!(Duration::days(42).to_string(), "P42D".to_string());
         assert_eq!(Duration::days(-42).to_string(), "P-42D".to_string());
         assert_eq!(Duration::seconds(42).to_string(), "PT42S".to_string());