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.
11 //! Synchronous Timers
13 //! This module exposes the functionality to create timers, block the current task,
14 //! and create receivers which will receive notifications after a period of time.
16 // FIXME: These functions take Durations but only pass ms to the backend impls.
18 use sync::mpsc::{Receiver, Sender, channel};
21 use sys::timer::Callback;
22 use sys::timer::Timer as TimerImp;
24 /// A synchronous timer object
26 /// Values of this type can be used to put the current task to sleep for a
27 /// period of time. Handles to this timer can also be created in the form of
28 /// receivers which will receive notifications over time.
34 /// use std::io::Timer;
35 /// use std::time::Duration;
37 /// let mut timer = Timer::new().unwrap();
38 /// timer.sleep(Duration::milliseconds(10)); // block the task for awhile
40 /// let timeout = timer.oneshot(Duration::milliseconds(10));
42 /// timeout.recv().unwrap(); // wait for the timeout to expire
44 /// let periodic = timer.periodic(Duration::milliseconds(10));
46 /// periodic.recv().unwrap();
47 /// // this loop is only executed once every 10ms
52 /// If only sleeping is necessary, then a convenience API is provided through
53 /// the `io::timer` module.
57 /// use std::io::timer;
58 /// use std::time::Duration;
60 /// // Put this task to sleep for 5 seconds
61 /// timer::sleep(Duration::seconds(5));
68 struct TimerCallback { tx: Sender<()> }
70 /// Sleep the current task for the specified duration.
72 /// When provided a zero or negative `duration`, the function will
73 /// return immediately.
74 pub fn sleep(duration: Duration) {
75 let timer = Timer::new();
76 let mut timer = timer.ok().expect("timer::sleep: could not create a Timer");
82 /// Creates a new timer which can be used to put the current task to sleep
83 /// for a number of milliseconds, or to possibly create channels which will
84 /// get notified after an amount of time has passed.
85 pub fn new() -> IoResult<Timer> {
86 TimerImp::new().map(|t| Timer { inner: t })
89 /// Blocks the current task for the specified duration.
91 /// Note that this function will cause any other receivers for this timer to
92 /// be invalidated (the other end will be closed).
94 /// When provided a zero or negative `duration`, the function will
95 /// return immediately.
96 pub fn sleep(&mut self, duration: Duration) {
97 // Short-circuit the timer backend for 0 duration
98 let ms = in_ms_u64(duration);
100 self.inner.sleep(ms);
103 /// Creates a oneshot receiver which will have a notification sent when
104 /// the specified duration has elapsed.
106 /// This does *not* block the current task, but instead returns immediately.
108 /// Note that this invalidates any previous receiver which has been created
109 /// by this timer, and that the returned receiver will be invalidated once
110 /// the timer is destroyed (when it falls out of scope). In particular, if
111 /// this is called in method-chaining style, the receiver will be
112 /// invalidated at the end of that statement, and all `recv` calls will
118 /// use std::io::Timer;
119 /// use std::time::Duration;
121 /// let mut timer = Timer::new().unwrap();
122 /// let ten_milliseconds = timer.oneshot(Duration::milliseconds(10));
124 /// for _ in range(0u, 100) { /* do work */ }
126 /// // blocks until 10 ms after the `oneshot` call
127 /// ten_milliseconds.recv().unwrap();
131 /// use std::io::Timer;
132 /// use std::time::Duration;
134 /// // Incorrect, method chaining-style:
135 /// let mut five_ms = Timer::new().unwrap().oneshot(Duration::milliseconds(5));
136 /// // The timer object was destroyed, so this will always fail:
137 /// // five_ms.recv().unwrap()
140 /// When provided a zero or negative `duration`, the message will
141 /// be sent immediately.
142 pub fn oneshot(&mut self, duration: Duration) -> Receiver<()> {
143 let (tx, rx) = channel();
144 // Short-circuit the timer backend for 0 duration
145 if in_ms_u64(duration) != 0 {
146 self.inner.oneshot(in_ms_u64(duration), box TimerCallback { tx: tx });
148 tx.send(()).unwrap();
153 /// Creates a receiver which will have a continuous stream of notifications
154 /// being sent each time the specified duration has elapsed.
156 /// This does *not* block the current task, but instead returns
157 /// immediately. The first notification will not be received immediately,
158 /// but rather after the first duration.
160 /// Note that this invalidates any previous receiver which has been created
161 /// by this timer, and that the returned receiver will be invalidated once
162 /// the timer is destroyed (when it falls out of scope). In particular, if
163 /// this is called in method-chaining style, the receiver will be
164 /// invalidated at the end of that statement, and all `recv` calls will
170 /// use std::io::Timer;
171 /// use std::time::Duration;
173 /// let mut timer = Timer::new().unwrap();
174 /// let ten_milliseconds = timer.periodic(Duration::milliseconds(10));
176 /// for _ in range(0u, 100) { /* do work */ }
178 /// // blocks until 10 ms after the `periodic` call
179 /// ten_milliseconds.recv().unwrap();
181 /// for _ in range(0u, 100) { /* do work */ }
183 /// // blocks until 20 ms after the `periodic` call (*not* 10ms after the
184 /// // previous `recv`)
185 /// ten_milliseconds.recv().unwrap();
189 /// use std::io::Timer;
190 /// use std::time::Duration;
192 /// // Incorrect, method chaining-style.
193 /// let mut five_ms = Timer::new().unwrap().periodic(Duration::milliseconds(5));
194 /// // The timer object was destroyed, so this will always fail:
195 /// // five_ms.recv().unwrap()
198 /// When provided a zero or negative `duration`, the messages will
199 /// be sent without delay.
200 pub fn periodic(&mut self, duration: Duration) -> Receiver<()> {
201 let ms = in_ms_u64(duration);
202 // FIXME: The backend implementations don't ever send a message
203 // if given a 0 ms duration. Temporarily using 1ms. It's
204 // not clear what use a 0ms period is anyway...
205 let ms = if ms == 0 { 1 } else { ms };
206 let (tx, rx) = channel();
207 self.inner.period(ms, box TimerCallback { tx: tx });
212 impl Callback for TimerCallback {
214 let _ = self.tx.send(());
218 fn in_ms_u64(d: Duration) -> u64 {
219 let ms = d.num_milliseconds();
220 if ms < 0 { return 0 };
231 fn test_io_timer_sleep_simple() {
232 let mut timer = Timer::new().unwrap();
233 timer.sleep(Duration::milliseconds(1));
237 fn test_io_timer_sleep_oneshot() {
238 let mut timer = Timer::new().unwrap();
239 timer.oneshot(Duration::milliseconds(1)).recv().unwrap();
243 fn test_io_timer_sleep_oneshot_forget() {
244 let mut timer = Timer::new().unwrap();
245 timer.oneshot(Duration::milliseconds(100000000));
250 let mut timer = Timer::new().unwrap();
251 let rx1 = timer.oneshot(Duration::milliseconds(10000));
252 let rx = timer.oneshot(Duration::milliseconds(1));
254 assert!(rx1.recv().is_err());
258 fn test_io_timer_oneshot_then_sleep() {
259 let mut timer = Timer::new().unwrap();
260 let rx = timer.oneshot(Duration::milliseconds(100000000));
261 timer.sleep(Duration::milliseconds(1)); // this should invalidate rx
263 assert!(rx.recv().is_err());
267 fn test_io_timer_sleep_periodic() {
268 let mut timer = Timer::new().unwrap();
269 let rx = timer.periodic(Duration::milliseconds(1));
276 fn test_io_timer_sleep_periodic_forget() {
277 let mut timer = Timer::new().unwrap();
278 timer.periodic(Duration::milliseconds(100000000));
282 fn test_io_timer_sleep_standalone() {
283 super::sleep(Duration::milliseconds(1))
288 let mut timer = Timer::new().unwrap();
290 let rx = timer.oneshot(Duration::milliseconds(1));
292 assert!(rx.recv().is_err());
294 let rx = timer.oneshot(Duration::milliseconds(1));
296 assert!(rx.recv().is_err());
301 let mut timer = Timer::new().unwrap();
302 let orx = timer.oneshot(Duration::milliseconds(100));
303 let prx = timer.periodic(Duration::milliseconds(100));
304 timer.sleep(Duration::milliseconds(1));
305 assert!(orx.recv().is_err());
306 assert!(prx.recv().is_err());
307 timer.oneshot(Duration::milliseconds(1)).recv().unwrap();
312 let mut timer = Timer::new().unwrap();
313 let rx = timer.periodic(Duration::milliseconds(1));
316 let rx2 = timer.periodic(Duration::milliseconds(1));
323 let mut timer = Timer::new().unwrap();
324 timer.sleep(Duration::milliseconds(1));
325 timer.sleep(Duration::milliseconds(1));
331 let mut timer = Timer::new().unwrap();
332 let _rx = timer.oneshot(Duration::milliseconds(1));
339 let mut timer = Timer::new().unwrap();
340 let _rx = timer.periodic(Duration::milliseconds(1));
347 let _timer = Timer::new().unwrap();
352 fn closing_channel_during_drop_doesnt_kill_everything() {
354 let mut timer = Timer::new().unwrap();
355 let timer_rx = timer.periodic(Duration::milliseconds(1000));
357 Thread::spawn(move|| {
358 let _ = timer_rx.recv();
361 // when we drop the TimerWatcher we're going to destroy the channel,
362 // which must wake up the task on the other end
366 fn reset_doesnt_switch_tasks() {
367 // similar test to the one above.
368 let mut timer = Timer::new().unwrap();
369 let timer_rx = timer.periodic(Duration::milliseconds(1000));
371 Thread::spawn(move|| {
372 let _ = timer_rx.recv();
375 timer.oneshot(Duration::milliseconds(1));
379 fn reset_doesnt_switch_tasks2() {
380 // similar test to the one above.
381 let mut timer = Timer::new().unwrap();
382 let timer_rx = timer.periodic(Duration::milliseconds(1000));
384 Thread::spawn(move|| {
385 let _ = timer_rx.recv();
388 timer.sleep(Duration::milliseconds(1));
392 fn sender_goes_away_oneshot() {
394 let mut timer = Timer::new().unwrap();
395 timer.oneshot(Duration::milliseconds(1000))
397 assert!(rx.recv().is_err());
401 fn sender_goes_away_period() {
403 let mut timer = Timer::new().unwrap();
404 timer.periodic(Duration::milliseconds(1000))
406 assert!(rx.recv().is_err());
410 fn receiver_goes_away_oneshot() {
411 let mut timer1 = Timer::new().unwrap();
412 timer1.oneshot(Duration::milliseconds(1));
413 let mut timer2 = Timer::new().unwrap();
414 // while sleeping, the previous timer should fire and not have its
415 // callback do something terrible.
416 timer2.sleep(Duration::milliseconds(2));
420 fn receiver_goes_away_period() {
421 let mut timer1 = Timer::new().unwrap();
422 timer1.periodic(Duration::milliseconds(1));
423 let mut timer2 = Timer::new().unwrap();
424 // while sleeping, the previous timer should fire and not have its
425 // callback do something terrible.
426 timer2.sleep(Duration::milliseconds(2));
431 let mut timer = Timer::new().unwrap();
432 timer.sleep(Duration::milliseconds(0));
436 fn sleep_negative() {
437 let mut timer = Timer::new().unwrap();
438 timer.sleep(Duration::milliseconds(-1000000));
443 let mut timer = Timer::new().unwrap();
444 let rx = timer.oneshot(Duration::milliseconds(0));
449 fn oneshot_negative() {
450 let mut timer = Timer::new().unwrap();
451 let rx = timer.oneshot(Duration::milliseconds(-1000000));
457 let mut timer = Timer::new().unwrap();
458 let rx = timer.periodic(Duration::milliseconds(0));
466 fn periodic_negative() {
467 let mut timer = Timer::new().unwrap();
468 let rx = timer.periodic(Duration::milliseconds(-1000000));