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.
19 use sync::mpsc::{Receiver, Sender, channel};
22 use sys::timer::Callback;
23 use sys::timer::Timer as TimerImp;
25 /// A synchronous timer object
27 /// Values of this type can be used to put the current task to sleep for a
28 /// period of time. Handles to this timer can also be created in the form of
29 /// receivers which will receive notifications over time.
34 /// # #![feature(old_io, std_misc)]
36 /// use std::old_io::Timer;
37 /// use std::time::Duration;
39 /// let mut timer = Timer::new().unwrap();
40 /// timer.sleep(Duration::milliseconds(10)); // block the task for awhile
42 /// let timeout = timer.oneshot(Duration::milliseconds(10));
44 /// timeout.recv().unwrap(); // wait for the timeout to expire
46 /// let periodic = timer.periodic(Duration::milliseconds(10));
48 /// periodic.recv().unwrap();
49 /// // this loop is only executed once every 10ms
54 /// If only sleeping is necessary, then a convenience API is provided through
55 /// the `old_io::timer` module.
58 /// # #![feature(old_io, std_misc)]
60 /// use std::old_io::timer;
61 /// use std::time::Duration;
63 /// // Put this task to sleep for 5 seconds
64 /// timer::sleep(Duration::seconds(5));
71 struct TimerCallback { tx: Sender<()> }
73 /// Sleep the current task for the specified duration.
75 /// When provided a zero or negative `duration`, the function will
76 /// return immediately.
77 pub fn sleep(duration: Duration) {
78 let timer = Timer::new();
79 let mut timer = timer.ok().expect("timer::sleep: could not create a Timer");
85 /// Creates a new timer which can be used to put the current task to sleep
86 /// for a number of milliseconds, or to possibly create channels which will
87 /// get notified after an amount of time has passed.
88 pub fn new() -> IoResult<Timer> {
89 TimerImp::new().map(|t| Timer { inner: t })
92 /// Blocks the current task for the specified duration.
94 /// Note that this function will cause any other receivers for this timer to
95 /// be invalidated (the other end will be closed).
97 /// When provided a zero or negative `duration`, the function will
98 /// return immediately.
99 pub fn sleep(&mut self, duration: Duration) {
100 // Short-circuit the timer backend for 0 duration
101 let ms = in_ms_u64(duration);
102 if ms == 0 { return }
103 self.inner.sleep(ms);
106 /// Creates a oneshot receiver which will have a notification sent when
107 /// the specified duration has elapsed.
109 /// This does *not* block the current task, but instead returns immediately.
111 /// Note that this invalidates any previous receiver which has been created
112 /// by this timer, and that the returned receiver will be invalidated once
113 /// the timer is destroyed (when it falls out of scope). In particular, if
114 /// this is called in method-chaining style, the receiver will be
115 /// invalidated at the end of that statement, and all `recv` calls will
121 /// # #![feature(old_io, std_misc)]
122 /// use std::old_io::Timer;
123 /// use std::time::Duration;
125 /// let mut timer = Timer::new().unwrap();
126 /// let ten_milliseconds = timer.oneshot(Duration::milliseconds(10));
128 /// for _ in 0..100 { /* do work */ }
130 /// // blocks until 10 ms after the `oneshot` call
131 /// ten_milliseconds.recv().unwrap();
135 /// # #![feature(old_io, std_misc)]
136 /// use std::old_io::Timer;
137 /// use std::time::Duration;
139 /// // Incorrect, method chaining-style:
140 /// let mut five_ms = Timer::new().unwrap().oneshot(Duration::milliseconds(5));
141 /// // The timer object was destroyed, so this will always fail:
142 /// // five_ms.recv().unwrap()
145 /// When provided a zero or negative `duration`, the message will
146 /// be sent immediately.
147 pub fn oneshot(&mut self, duration: Duration) -> Receiver<()> {
148 let (tx, rx) = channel();
149 // Short-circuit the timer backend for 0 duration
150 if in_ms_u64(duration) != 0 {
151 self.inner.oneshot(in_ms_u64(duration), Box::new(TimerCallback { tx: tx }));
153 tx.send(()).unwrap();
158 /// Creates a receiver which will have a continuous stream of notifications
159 /// being sent each time the specified duration has elapsed.
161 /// This does *not* block the current task, but instead returns
162 /// immediately. The first notification will not be received immediately,
163 /// but rather after the first duration.
165 /// Note that this invalidates any previous receiver which has been created
166 /// by this timer, and that the returned receiver will be invalidated once
167 /// the timer is destroyed (when it falls out of scope). In particular, if
168 /// this is called in method-chaining style, the receiver will be
169 /// invalidated at the end of that statement, and all `recv` calls will
175 /// # #![feature(old_io, std_misc)]
176 /// use std::old_io::Timer;
177 /// use std::time::Duration;
179 /// let mut timer = Timer::new().unwrap();
180 /// let ten_milliseconds = timer.periodic(Duration::milliseconds(10));
182 /// for _ in 0..100 { /* do work */ }
184 /// // blocks until 10 ms after the `periodic` call
185 /// ten_milliseconds.recv().unwrap();
187 /// for _ in 0..100 { /* do work */ }
189 /// // blocks until 20 ms after the `periodic` call (*not* 10ms after the
190 /// // previous `recv`)
191 /// ten_milliseconds.recv().unwrap();
195 /// # #![feature(old_io, std_misc)]
196 /// use std::old_io::Timer;
197 /// use std::time::Duration;
199 /// // Incorrect, method chaining-style.
200 /// let mut five_ms = Timer::new().unwrap().periodic(Duration::milliseconds(5));
201 /// // The timer object was destroyed, so this will always fail:
202 /// // five_ms.recv().unwrap()
205 /// When provided a zero or negative `duration`, the messages will
206 /// be sent without delay.
207 pub fn periodic(&mut self, duration: Duration) -> Receiver<()> {
208 let ms = in_ms_u64(duration);
209 // FIXME: The backend implementations don't ever send a message
210 // if given a 0 ms duration. Temporarily using 1ms. It's
211 // not clear what use a 0ms period is anyway...
212 let ms = if ms == 0 { 1 } else { ms };
213 let (tx, rx) = channel();
214 self.inner.period(ms, Box::new(TimerCallback { tx: tx }));
219 impl Callback for TimerCallback {
221 let _ = self.tx.send(());
225 fn in_ms_u64(d: Duration) -> u64 {
226 let ms = d.num_milliseconds();
227 if ms < 0 { return 0 };
238 fn test_timer_send() {
239 let mut timer = Timer::new().unwrap();
240 thread::spawn(move || timer.sleep(Duration::milliseconds(1)));
244 fn test_io_timer_sleep_simple() {
245 let mut timer = Timer::new().unwrap();
246 timer.sleep(Duration::milliseconds(1));
250 fn test_io_timer_sleep_oneshot() {
251 let mut timer = Timer::new().unwrap();
252 timer.oneshot(Duration::milliseconds(1)).recv().unwrap();
256 fn test_io_timer_sleep_oneshot_forget() {
257 let mut timer = Timer::new().unwrap();
258 timer.oneshot(Duration::milliseconds(100000000));
263 let mut timer = Timer::new().unwrap();
264 let rx1 = timer.oneshot(Duration::milliseconds(10000));
265 let rx = timer.oneshot(Duration::milliseconds(1));
267 assert!(rx1.recv().is_err());
271 fn test_io_timer_oneshot_then_sleep() {
272 let mut timer = Timer::new().unwrap();
273 let rx = timer.oneshot(Duration::milliseconds(100000000));
274 timer.sleep(Duration::milliseconds(1)); // this should invalidate rx
276 assert!(rx.recv().is_err());
280 fn test_io_timer_sleep_periodic() {
281 let mut timer = Timer::new().unwrap();
282 let rx = timer.periodic(Duration::milliseconds(1));
289 fn test_io_timer_sleep_periodic_forget() {
290 let mut timer = Timer::new().unwrap();
291 timer.periodic(Duration::milliseconds(100000000));
295 fn test_io_timer_sleep_standalone() {
296 super::sleep(Duration::milliseconds(1))
301 let mut timer = Timer::new().unwrap();
303 let rx = timer.oneshot(Duration::milliseconds(1));
305 assert!(rx.recv().is_err());
307 let rx = timer.oneshot(Duration::milliseconds(1));
309 assert!(rx.recv().is_err());
314 let mut timer = Timer::new().unwrap();
315 let orx = timer.oneshot(Duration::milliseconds(100));
316 let prx = timer.periodic(Duration::milliseconds(100));
317 timer.sleep(Duration::milliseconds(1));
318 assert!(orx.recv().is_err());
319 assert!(prx.recv().is_err());
320 timer.oneshot(Duration::milliseconds(1)).recv().unwrap();
325 let mut timer = Timer::new().unwrap();
326 let rx = timer.periodic(Duration::milliseconds(1));
329 let rx2 = timer.periodic(Duration::milliseconds(1));
336 let mut timer = Timer::new().unwrap();
337 timer.sleep(Duration::milliseconds(1));
338 timer.sleep(Duration::milliseconds(1));
344 let mut timer = Timer::new().unwrap();
345 let _rx = timer.oneshot(Duration::milliseconds(1));
352 let mut timer = Timer::new().unwrap();
353 let _rx = timer.periodic(Duration::milliseconds(1));
360 let _timer = Timer::new().unwrap();
365 fn closing_channel_during_drop_doesnt_kill_everything() {
367 let mut timer = Timer::new().unwrap();
368 let timer_rx = timer.periodic(Duration::milliseconds(1000));
370 thread::spawn(move|| {
371 let _ = timer_rx.recv();
374 // when we drop the TimerWatcher we're going to destroy the channel,
375 // which must wake up the task on the other end
379 fn reset_doesnt_switch_tasks() {
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.oneshot(Duration::milliseconds(1));
392 fn reset_doesnt_switch_tasks2() {
393 // similar test to the one above.
394 let mut timer = Timer::new().unwrap();
395 let timer_rx = timer.periodic(Duration::milliseconds(1000));
397 thread::spawn(move|| {
398 let _ = timer_rx.recv();
401 timer.sleep(Duration::milliseconds(1));
405 fn sender_goes_away_oneshot() {
407 let mut timer = Timer::new().unwrap();
408 timer.oneshot(Duration::milliseconds(1000))
410 assert!(rx.recv().is_err());
414 fn sender_goes_away_period() {
416 let mut timer = Timer::new().unwrap();
417 timer.periodic(Duration::milliseconds(1000))
419 assert!(rx.recv().is_err());
423 fn receiver_goes_away_oneshot() {
424 let mut timer1 = Timer::new().unwrap();
425 timer1.oneshot(Duration::milliseconds(1));
426 let mut timer2 = Timer::new().unwrap();
427 // while sleeping, the previous timer should fire and not have its
428 // callback do something terrible.
429 timer2.sleep(Duration::milliseconds(2));
433 fn receiver_goes_away_period() {
434 let mut timer1 = Timer::new().unwrap();
435 timer1.periodic(Duration::milliseconds(1));
436 let mut timer2 = Timer::new().unwrap();
437 // while sleeping, the previous timer should fire and not have its
438 // callback do something terrible.
439 timer2.sleep(Duration::milliseconds(2));
444 let mut timer = Timer::new().unwrap();
445 timer.sleep(Duration::milliseconds(0));
449 fn sleep_negative() {
450 let mut timer = Timer::new().unwrap();
451 timer.sleep(Duration::milliseconds(-1000000));
456 let mut timer = Timer::new().unwrap();
457 let rx = timer.oneshot(Duration::milliseconds(0));
462 fn oneshot_negative() {
463 let mut timer = Timer::new().unwrap();
464 let rx = timer.oneshot(Duration::milliseconds(-1000000));
470 let mut timer = Timer::new().unwrap();
471 let rx = timer.periodic(Duration::milliseconds(0));
479 fn periodic_negative() {
480 let mut timer = Timer::new().unwrap();
481 let rx = timer.periodic(Duration::milliseconds(-1000000));