rust/src/libstd/io/timer.rs

187 lines
5.2 KiB
Rust
Raw Normal View History

2013-07-19 18:24:07 -05:00
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2013-07-19 18:03:02 -05:00
// file at the top-level directory of this distribution and at
2013-07-19 18:24:07 -05:00
// http://rust-lang.org/COPYRIGHT.
2013-07-19 18:03:02 -05:00
//
2013-07-19 18:24:07 -05:00
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
2013-07-19 18:03:02 -05:00
// except according to those terms.
2013-07-19 18:24:07 -05:00
/*!
Synchronous Timers
This module exposes the functionality to create timers, block the current task,
and create ports which will receive notifications after a period of time.
# Example
```rust
2013-11-11 00:46:32 -06:00
use std::io::Timer;
let mut timer = Timer::new().unwrap();
timer.sleep(10); // block the task for awhile
let timeout = timer.oneshot(10);
// do some work
timeout.recv(); // wait for the timeout to expire
let periodic = timer.periodic(10);
loop {
periodic.recv();
// this loop is only executed once every 10ms
}
```
*/
use comm::{Port, PortOne};
2013-07-19 18:03:02 -05:00
use option::{Option, Some, None};
use result::{Ok, Err};
2013-11-11 00:46:32 -06:00
use io::io_error;
use rt::rtio::{IoFactory, RtioTimer, with_local_io};
2013-07-19 18:03:02 -05:00
pub struct Timer {
priv obj: ~RtioTimer
}
2013-07-19 18:03:02 -05:00
/// Sleep the current task for `msecs` milliseconds.
pub fn sleep(msecs: u64) {
let mut timer = Timer::new().expect("timer::sleep: could not create a Timer");
timer.sleep(msecs)
}
2013-07-19 18:03:02 -05:00
impl Timer {
/// Creates a new timer which can be used to put the current task to sleep
/// for a number of milliseconds, or to possibly create channels which will
/// get notified after an amount of time has passed.
pub fn new() -> Option<Timer> {
with_local_io(|io| {
match io.timer_init() {
Ok(t) => Some(Timer { obj: t }),
Err(ioerr) => {
2013-11-11 00:46:32 -06:00
debug!("Timer::init: failed to init: {:?}", ioerr);
io_error::cond.raise(ioerr);
None
}
2013-07-19 18:03:02 -05:00
}
})
2013-07-19 18:03:02 -05:00
}
/// Blocks the current task for `msecs` milliseconds.
///
/// Note that this function will cause any other ports for this timer to be
/// invalidated (the other end will be closed).
2013-08-20 11:53:02 -05:00
pub fn sleep(&mut self, msecs: u64) {
self.obj.sleep(msecs);
2013-07-19 18:03:02 -05:00
}
/// Creates a oneshot port which will have a notification sent when `msecs`
/// milliseconds has elapsed. This does *not* block the current task, but
/// instead returns immediately.
///
/// Note that this invalidates any previous port which has been created by
/// this timer, and that the returned port will be invalidated once the
/// timer is destroyed (when it falls out of scope).
pub fn oneshot(&mut self, msecs: u64) -> PortOne<()> {
self.obj.oneshot(msecs)
}
/// Creates a port which will have a continuous stream of notifications
/// being sent every `msecs` milliseconds. This does *not* block the
/// current task, but instead returns immediately. The first notification
/// will not be received immediately, but rather after `msec` milliseconds
/// have passed.
///
/// Note that this invalidates any previous port which has been created by
/// this timer, and that the returned port will be invalidated once the
/// timer is destroyed (when it falls out of scope).
pub fn periodic(&mut self, msecs: u64) -> Port<()> {
self.obj.period(msecs)
}
2013-07-19 18:03:02 -05:00
}
#[cfg(test)]
mod test {
use prelude::*;
2013-07-19 18:03:02 -05:00
use super::*;
use rt::test::*;
2013-07-19 18:03:02 -05:00
#[test]
fn test_io_timer_sleep_simple() {
do run_in_mt_newsched_task {
let mut timer = Timer::new().unwrap();
timer.sleep(1);
}
}
#[test]
fn test_io_timer_sleep_oneshot() {
do run_in_mt_newsched_task {
let mut timer = Timer::new().unwrap();
timer.oneshot(1).recv();
}
}
#[test]
fn test_io_timer_sleep_oneshot_forget() {
do run_in_mt_newsched_task {
let mut timer = Timer::new().unwrap();
timer.oneshot(100000000000);
}
}
#[test]
fn oneshot_twice() {
do run_in_mt_newsched_task {
let mut timer = Timer::new().unwrap();
2013-11-09 13:02:16 -06:00
let port1 = timer.oneshot(10000);
let port = timer.oneshot(1);
port.recv();
2013-11-09 13:02:16 -06:00
assert_eq!(port1.try_recv(), None);
}
}
#[test]
fn test_io_timer_oneshot_then_sleep() {
do run_in_mt_newsched_task {
let mut timer = Timer::new().unwrap();
let port = timer.oneshot(100000000000);
timer.sleep(1); // this should invalidate the port
assert_eq!(port.try_recv(), None);
}
}
#[test]
fn test_io_timer_sleep_periodic() {
do run_in_mt_newsched_task {
let mut timer = Timer::new().unwrap();
let port = timer.periodic(1);
port.recv();
port.recv();
port.recv();
}
}
#[test]
fn test_io_timer_sleep_periodic_forget() {
do run_in_mt_newsched_task {
let mut timer = Timer::new().unwrap();
timer.periodic(100000000000);
2013-07-19 18:03:02 -05:00
}
}
#[test]
fn test_io_timer_sleep_standalone() {
do run_in_mt_newsched_task {
sleep(1)
}
}
}