1 // Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
15 This module exposes the functionality to create timers, block the current task,
16 and create receivers which will receive notifications after a period of time.
20 use comm::{Receiver, Sender, channel};
21 use io::{IoResult, IoError};
24 use rt::rtio::{IoFactory, LocalIo, RtioTimer, Callback};
26 /// A synchronous timer object
28 /// Values of this type can be used to put the current task to sleep for a
29 /// period of time. Handles to this timer can also be created in the form of
30 /// receivers which will receive notifications over time.
37 /// use std::io::Timer;
39 /// let mut timer = Timer::new().unwrap();
40 /// timer.sleep(10); // block the task for awhile
42 /// let timeout = timer.oneshot(10);
44 /// timeout.recv(); // wait for the timeout to expire
46 /// let periodic = timer.periodic(10);
49 /// // this loop is only executed once every 10ms
54 /// If only sleeping is necessary, then a convenience API is provided through
55 /// the `io::timer` module.
60 /// use std::io::timer;
62 /// // Put this task to sleep for 5 seconds
63 /// timer::sleep(5000);
67 obj: Box<RtioTimer + Send>,
70 struct TimerCallback { tx: Sender<()> }
72 /// Sleep the current task for `msecs` milliseconds.
73 pub fn sleep(msecs: u64) {
74 let timer = Timer::new();
75 let mut timer = timer.ok().expect("timer::sleep: could not create a Timer");
81 /// Creates a new timer which can be used to put the current task to sleep
82 /// for a number of milliseconds, or to possibly create channels which will
83 /// get notified after an amount of time has passed.
84 pub fn new() -> IoResult<Timer> {
85 LocalIo::maybe_raise(|io| {
86 io.timer_init().map(|t| Timer { obj: t })
87 }).map_err(IoError::from_rtio_error)
90 /// Blocks the current task for `msecs` milliseconds.
92 /// Note that this function will cause any other receivers for this timer to
93 /// be invalidated (the other end will be closed).
94 pub fn sleep(&mut self, msecs: u64) {
95 self.obj.sleep(msecs);
98 /// Creates a oneshot receiver which will have a notification sent when
99 /// `msecs` milliseconds has elapsed.
101 /// This does *not* block the current task, but instead returns immediately.
103 /// Note that this invalidates any previous receiver which has been created
104 /// by this timer, and that the returned receiver will be invalidated once
105 /// the timer is destroyed (when it falls out of scope). In particular, if
106 /// this is called in method-chaining style, the receiver will be
107 /// invalidated at the end of that statement, and all `recv` calls will
113 /// use std::io::Timer;
115 /// let mut timer = Timer::new().unwrap();
116 /// let ten_milliseconds = timer.oneshot(10);
118 /// for _ in range(0u, 100) { /* do work */ }
120 /// // blocks until 10 ms after the `oneshot` call
121 /// ten_milliseconds.recv();
125 /// use std::io::Timer;
127 /// // Incorrect, method chaining-style:
128 /// let mut five_ms = Timer::new().unwrap().oneshot(5);
129 /// // The timer object was destroyed, so this will always fail:
130 /// // five_ms.recv()
132 pub fn oneshot(&mut self, msecs: u64) -> Receiver<()> {
133 let (tx, rx) = channel();
134 self.obj.oneshot(msecs, box TimerCallback { tx: tx });
138 /// Creates a receiver which will have a continuous stream of notifications
139 /// being sent every `msecs` milliseconds.
141 /// This does *not* block the current task, but instead returns
142 /// immediately. The first notification will not be received immediately,
143 /// but rather after `msec` milliseconds have passed.
145 /// Note that this invalidates any previous receiver which has been created
146 /// by this timer, and that the returned receiver will be invalidated once
147 /// the timer is destroyed (when it falls out of scope). In particular, if
148 /// this is called in method-chaining style, the receiver will be
149 /// invalidated at the end of that statement, and all `recv` calls will
155 /// use std::io::Timer;
157 /// let mut timer = Timer::new().unwrap();
158 /// let ten_milliseconds = timer.periodic(10);
160 /// for _ in range(0u, 100) { /* do work */ }
162 /// // blocks until 10 ms after the `periodic` call
163 /// ten_milliseconds.recv();
165 /// for _ in range(0u, 100) { /* do work */ }
167 /// // blocks until 20 ms after the `periodic` call (*not* 10ms after the
168 /// // previous `recv`)
169 /// ten_milliseconds.recv();
173 /// use std::io::Timer;
175 /// // Incorrect, method chaining-style.
176 /// let mut five_ms = Timer::new().unwrap().periodic(5);
177 /// // The timer object was destroyed, so this will always fail:
178 /// // five_ms.recv()
180 pub fn periodic(&mut self, msecs: u64) -> Receiver<()> {
181 let (tx, rx) = channel();
182 self.obj.period(msecs, box TimerCallback { tx: tx });
187 impl Callback for TimerCallback {
189 let _ = self.tx.send_opt(());
195 iotest!(fn test_io_timer_sleep_simple() {
196 let mut timer = Timer::new().unwrap();
200 iotest!(fn test_io_timer_sleep_oneshot() {
201 let mut timer = Timer::new().unwrap();
202 timer.oneshot(1).recv();
205 iotest!(fn test_io_timer_sleep_oneshot_forget() {
206 let mut timer = Timer::new().unwrap();
207 timer.oneshot(100000000000);
210 iotest!(fn oneshot_twice() {
211 let mut timer = Timer::new().unwrap();
212 let rx1 = timer.oneshot(10000);
213 let rx = timer.oneshot(1);
215 assert_eq!(rx1.recv_opt(), Err(()));
218 iotest!(fn test_io_timer_oneshot_then_sleep() {
219 let mut timer = Timer::new().unwrap();
220 let rx = timer.oneshot(100000000000);
221 timer.sleep(1); // this should invalidate rx
223 assert_eq!(rx.recv_opt(), Err(()));
226 iotest!(fn test_io_timer_sleep_periodic() {
227 let mut timer = Timer::new().unwrap();
228 let rx = timer.periodic(1);
234 iotest!(fn test_io_timer_sleep_periodic_forget() {
235 let mut timer = Timer::new().unwrap();
236 timer.periodic(100000000000);
239 iotest!(fn test_io_timer_sleep_standalone() {
243 iotest!(fn oneshot() {
244 let mut timer = Timer::new().unwrap();
246 let rx = timer.oneshot(1);
248 assert!(rx.recv_opt().is_err());
250 let rx = timer.oneshot(1);
252 assert!(rx.recv_opt().is_err());
255 iotest!(fn override() {
256 let mut timer = Timer::new().unwrap();
257 let orx = timer.oneshot(100);
258 let prx = timer.periodic(100);
260 assert_eq!(orx.recv_opt(), Err(()));
261 assert_eq!(prx.recv_opt(), Err(()));
262 timer.oneshot(1).recv();
265 iotest!(fn period() {
266 let mut timer = Timer::new().unwrap();
267 let rx = timer.periodic(1);
270 let rx2 = timer.periodic(1);
276 let mut timer = Timer::new().unwrap();
281 iotest!(fn oneshot_fail() {
282 let mut timer = Timer::new().unwrap();
283 let _rx = timer.oneshot(1);
287 iotest!(fn period_fail() {
288 let mut timer = Timer::new().unwrap();
289 let _rx = timer.periodic(1);
293 iotest!(fn normal_fail() {
294 let _timer = Timer::new().unwrap();
298 iotest!(fn closing_channel_during_drop_doesnt_kill_everything() {
300 let mut timer = Timer::new().unwrap();
301 let timer_rx = timer.periodic(1000);
304 let _ = timer_rx.recv_opt();
307 // when we drop the TimerWatcher we're going to destroy the channel,
308 // which must wake up the task on the other end
311 iotest!(fn reset_doesnt_switch_tasks() {
312 // similar test to the one above.
313 let mut timer = Timer::new().unwrap();
314 let timer_rx = timer.periodic(1000);
317 let _ = timer_rx.recv_opt();
323 iotest!(fn reset_doesnt_switch_tasks2() {
324 // similar test to the one above.
325 let mut timer = Timer::new().unwrap();
326 let timer_rx = timer.periodic(1000);
329 let _ = timer_rx.recv_opt();
335 iotest!(fn sender_goes_away_oneshot() {
337 let mut timer = Timer::new().unwrap();
340 assert_eq!(rx.recv_opt(), Err(()));
343 iotest!(fn sender_goes_away_period() {
345 let mut timer = Timer::new().unwrap();
348 assert_eq!(rx.recv_opt(), Err(()));
351 iotest!(fn receiver_goes_away_oneshot() {
352 let mut timer1 = Timer::new().unwrap();
354 let mut timer2 = Timer::new().unwrap();
355 // while sleeping, the previous timer should fire and not have its
356 // callback do something terrible.
360 iotest!(fn receiver_goes_away_period() {
361 let mut timer1 = Timer::new().unwrap();
363 let mut timer2 = Timer::new().unwrap();
364 // while sleeping, the previous timer should fire and not have its
365 // callback do something terrible.