diff options
| author | Brian Anderson <banderson@mozilla.com> | 2014-07-30 20:07:41 -0700 |
|---|---|---|
| committer | Brian Anderson <banderson@mozilla.com> | 2014-08-13 11:31:47 -0700 |
| commit | 63cd4acf535f8df177459559fe2d7e6ab390c6d8 (patch) | |
| tree | 4f10ee436e87176f9141071d2a7a13d5ee499ba8 | |
| parent | 734834c7d6e4862c8348a8c9660bb338773047ca (diff) | |
| download | rust-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.rs | 2 | ||||
| -rw-r--r-- | src/libstd/io/signal.rs | 7 | ||||
| -rw-r--r-- | src/libstd/io/test.rs | 1 | ||||
| -rw-r--r-- | src/libstd/io/timer.rs | 89 | ||||
| -rw-r--r-- | src/libstd/task.rs | 3 | ||||
| -rw-r--r-- | src/libstd/time.rs | 40 |
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()); |
