]> git.lizzy.rs Git - rust.git/blob - src/libstd/io/timer.rs
Fixed tidy errors
[rust.git] / src / libstd / io / timer.rs
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.
4 //
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.
10
11 /*!
12
13 Synchronous Timers
14
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.
17
18 */
19
20 // FIXME: These functions take Durations but only pass ms to the backend impls.
21
22 use comm::{Receiver, Sender, channel};
23 use time::Duration;
24 use io::{IoResult, IoError};
25 use kinds::Send;
26 use boxed::Box;
27 use rt::rtio::{IoFactory, LocalIo, RtioTimer, Callback};
28
29 /// A synchronous timer object
30 ///
31 /// Values of this type can be used to put the current task to sleep for a
32 /// period of time. Handles to this timer can also be created in the form of
33 /// receivers which will receive notifications over time.
34 ///
35 /// # Example
36 ///
37 /// ```
38 /// # fn main() {}
39 /// # fn foo() {
40 /// use std::io::Timer;
41 /// use std::time::Duration;
42 ///
43 /// let mut timer = Timer::new().unwrap();
44 /// timer.sleep(Duration::milliseconds(10)); // block the task for awhile
45 ///
46 /// let timeout = timer.oneshot(Duration::milliseconds(10));
47 /// // do some work
48 /// timeout.recv(); // wait for the timeout to expire
49 ///
50 /// let periodic = timer.periodic(Duration::milliseconds(10));
51 /// loop {
52 ///     periodic.recv();
53 ///     // this loop is only executed once every 10ms
54 /// }
55 /// # }
56 /// ```
57 ///
58 /// If only sleeping is necessary, then a convenience API is provided through
59 /// the `io::timer` module.
60 ///
61 /// ```
62 /// # fn main() {}
63 /// # fn foo() {
64 /// use std::io::timer;
65 /// use std::time::Duration;
66 ///
67 /// // Put this task to sleep for 5 seconds
68 /// timer::sleep(Duration::seconds(5));
69 /// # }
70 /// ```
71 pub struct Timer {
72     obj: Box<RtioTimer + Send>,
73 }
74
75 struct TimerCallback { tx: Sender<()> }
76
77 /// Sleep the current task for the specified duration.
78 ///
79 /// When provided a zero or negative `duration`, the function will
80 /// return immediately.
81 pub fn sleep(duration: Duration) {
82     let timer = Timer::new();
83     let mut timer = timer.ok().expect("timer::sleep: could not create a Timer");
84
85     timer.sleep(duration)
86 }
87
88 impl Timer {
89     /// Creates a new timer which can be used to put the current task to sleep
90     /// for a number of milliseconds, or to possibly create channels which will
91     /// get notified after an amount of time has passed.
92     pub fn new() -> IoResult<Timer> {
93         LocalIo::maybe_raise(|io| {
94             io.timer_init().map(|t| Timer { obj: t })
95         }).map_err(IoError::from_rtio_error)
96     }
97
98     /// Blocks the current task for the specified duration.
99     ///
100     /// Note that this function will cause any other receivers for this timer to
101     /// be invalidated (the other end will be closed).
102     ///
103     /// When provided a zero or negative `duration`, the function will
104     /// return immediately.
105     pub fn sleep(&mut self, duration: Duration) {
106         // Short-circuit the timer backend for 0 duration
107         let ms = in_ms_u64(duration);
108         if ms == 0 { return }
109         self.obj.sleep(ms);
110     }
111
112     /// Creates a oneshot receiver which will have a notification sent when
113     /// the specified duration has elapsed.
114     ///
115     /// This does *not* block the current task, but instead returns immediately.
116     ///
117     /// Note that this invalidates any previous receiver which has been created
118     /// by this timer, and that the returned receiver will be invalidated once
119     /// the timer is destroyed (when it falls out of scope). In particular, if
120     /// this is called in method-chaining style, the receiver will be
121     /// invalidated at the end of that statement, and all `recv` calls will
122     /// fail.
123     ///
124     /// # Example
125     ///
126     /// ```rust
127     /// use std::io::Timer;
128     /// use std::time::Duration;
129     ///
130     /// let mut timer = Timer::new().unwrap();
131     /// let ten_milliseconds = timer.oneshot(Duration::milliseconds(10));
132     ///
133     /// for _ in range(0u, 100) { /* do work */ }
134     ///
135     /// // blocks until 10 ms after the `oneshot` call
136     /// ten_milliseconds.recv();
137     /// ```
138     ///
139     /// ```rust
140     /// use std::io::Timer;
141     /// use std::time::Duration;
142     ///
143     /// // Incorrect, method chaining-style:
144     /// let mut five_ms = Timer::new().unwrap().oneshot(Duration::milliseconds(5));
145     /// // The timer object was destroyed, so this will always fail:
146     /// // five_ms.recv()
147     /// ```
148     ///
149     /// When provided a zero or negative `duration`, the message will
150     /// be sent immediately.
151     pub fn oneshot(&mut self, duration: Duration) -> Receiver<()> {
152         let (tx, rx) = channel();
153         // Short-circuit the timer backend for 0 duration
154         if in_ms_u64(duration) != 0 {
155             self.obj.oneshot(in_ms_u64(duration), box TimerCallback { tx: tx });
156         } else {
157             tx.send(());
158         }
159         return rx
160     }
161
162     /// Creates a receiver which will have a continuous stream of notifications
163     /// being sent each time the specified duration has elapsed.
164     ///
165     /// This does *not* block the current task, but instead returns
166     /// immediately. The first notification will not be received immediately,
167     /// but rather after the first duration.
168     ///
169     /// Note that this invalidates any previous receiver which has been created
170     /// by this timer, and that the returned receiver will be invalidated once
171     /// the timer is destroyed (when it falls out of scope). In particular, if
172     /// this is called in method-chaining style, the receiver will be
173     /// invalidated at the end of that statement, and all `recv` calls will
174     /// fail.
175     ///
176     /// # Example
177     ///
178     /// ```rust
179     /// use std::io::Timer;
180     /// use std::time::Duration;
181     ///
182     /// let mut timer = Timer::new().unwrap();
183     /// let ten_milliseconds = timer.periodic(Duration::milliseconds(10));
184     ///
185     /// for _ in range(0u, 100) { /* do work */ }
186     ///
187     /// // blocks until 10 ms after the `periodic` call
188     /// ten_milliseconds.recv();
189     ///
190     /// for _ in range(0u, 100) { /* do work */ }
191     ///
192     /// // blocks until 20 ms after the `periodic` call (*not* 10ms after the
193     /// // previous `recv`)
194     /// ten_milliseconds.recv();
195     /// ```
196     ///
197     /// ```rust
198     /// use std::io::Timer;
199     /// use std::time::Duration;
200     ///
201     /// // Incorrect, method chaining-style.
202     /// let mut five_ms = Timer::new().unwrap().periodic(Duration::milliseconds(5));
203     /// // The timer object was destroyed, so this will always fail:
204     /// // five_ms.recv()
205     /// ```
206     ///
207     /// When provided a zero or negative `duration`, the messages will
208     /// be sent without delay.
209     pub fn periodic(&mut self, duration: Duration) -> Receiver<()> {
210         let ms = in_ms_u64(duration);
211         // FIXME: The backend implementations don't ever send a message
212         // if given a 0 ms duration. Temporarily using 1ms. It's
213         // not clear what use a 0ms period is anyway...
214         let ms = if ms == 0 { 1 } else { ms };
215         let (tx, rx) = channel();
216         self.obj.period(ms, box TimerCallback { tx: tx });
217         return rx
218     }
219 }
220
221 impl Callback for TimerCallback {
222     fn call(&mut self) {
223         let _ = self.tx.send_opt(());
224     }
225 }
226
227 fn in_ms_u64(d: Duration) -> u64 {
228     let ms = d.num_milliseconds();
229     if ms < 0 { return 0 };
230     return ms as u64;
231 }
232
233 #[cfg(test)]
234 mod test {
235     use super::*;
236     use time::Duration;
237     use task::spawn;
238     use prelude::*;
239
240     #[test]
241     fn test_io_timer_sleep_simple() {
242         let mut timer = Timer::new().unwrap();
243         timer.sleep(Duration::milliseconds(1));
244     }
245
246     #[test]
247     fn test_io_timer_sleep_oneshot() {
248         let mut timer = Timer::new().unwrap();
249         timer.oneshot(Duration::milliseconds(1)).recv();
250     }
251
252     #[test]
253     fn test_io_timer_sleep_oneshot_forget() {
254         let mut timer = Timer::new().unwrap();
255         timer.oneshot(Duration::milliseconds(100000000));
256     }
257
258     #[test]
259     fn oneshot_twice() {
260         let mut timer = Timer::new().unwrap();
261         let rx1 = timer.oneshot(Duration::milliseconds(10000));
262         let rx = timer.oneshot(Duration::milliseconds(1));
263         rx.recv();
264         assert_eq!(rx1.recv_opt(), Err(()));
265     }
266
267     #[test]
268     fn test_io_timer_oneshot_then_sleep() {
269         let mut timer = Timer::new().unwrap();
270         let rx = timer.oneshot(Duration::milliseconds(100000000));
271         timer.sleep(Duration::milliseconds(1)); // this should invalidate rx
272
273         assert_eq!(rx.recv_opt(), Err(()));
274     }
275
276     #[test]
277     fn test_io_timer_sleep_periodic() {
278         let mut timer = Timer::new().unwrap();
279         let rx = timer.periodic(Duration::milliseconds(1));
280         rx.recv();
281         rx.recv();
282         rx.recv();
283     }
284
285     #[test]
286     fn test_io_timer_sleep_periodic_forget() {
287         let mut timer = Timer::new().unwrap();
288         timer.periodic(Duration::milliseconds(100000000));
289     }
290
291     #[test]
292     fn test_io_timer_sleep_standalone() {
293         super::sleep(Duration::milliseconds(1))
294     }
295
296     #[test]
297     fn oneshot() {
298         let mut timer = Timer::new().unwrap();
299
300         let rx = timer.oneshot(Duration::milliseconds(1));
301         rx.recv();
302         assert!(rx.recv_opt().is_err());
303
304         let rx = timer.oneshot(Duration::milliseconds(1));
305         rx.recv();
306         assert!(rx.recv_opt().is_err());
307     }
308
309     #[test]
310     fn test_override() {
311         let mut timer = Timer::new().unwrap();
312         let orx = timer.oneshot(Duration::milliseconds(100));
313         let prx = timer.periodic(Duration::milliseconds(100));
314         timer.sleep(Duration::milliseconds(1));
315         assert_eq!(orx.recv_opt(), Err(()));
316         assert_eq!(prx.recv_opt(), Err(()));
317         timer.oneshot(Duration::milliseconds(1)).recv();
318     }
319
320     #[test]
321     fn period() {
322         let mut timer = Timer::new().unwrap();
323         let rx = timer.periodic(Duration::milliseconds(1));
324         rx.recv();
325         rx.recv();
326         let rx2 = timer.periodic(Duration::milliseconds(1));
327         rx2.recv();
328         rx2.recv();
329     }
330
331     #[test]
332     fn sleep() {
333         let mut timer = Timer::new().unwrap();
334         timer.sleep(Duration::milliseconds(1));
335         timer.sleep(Duration::milliseconds(1));
336     }
337
338     #[test]
339     #[should_fail]
340     fn oneshot_fail() {
341         let mut timer = Timer::new().unwrap();
342         let _rx = timer.oneshot(Duration::milliseconds(1));
343         panic!();
344     }
345
346     #[test]
347     #[should_fail]
348     fn period_fail() {
349         let mut timer = Timer::new().unwrap();
350         let _rx = timer.periodic(Duration::milliseconds(1));
351         panic!();
352     }
353
354     #[test]
355     #[should_fail]
356     fn normal_fail() {
357         let _timer = Timer::new().unwrap();
358         panic!();
359     }
360
361     #[test]
362     fn closing_channel_during_drop_doesnt_kill_everything() {
363         // see issue #10375
364         let mut timer = Timer::new().unwrap();
365         let timer_rx = timer.periodic(Duration::milliseconds(1000));
366
367         spawn(proc() {
368             let _ = timer_rx.recv_opt();
369         });
370
371         // when we drop the TimerWatcher we're going to destroy the channel,
372         // which must wake up the task on the other end
373     }
374
375     #[test]
376     fn reset_doesnt_switch_tasks() {
377         // similar test to the one above.
378         let mut timer = Timer::new().unwrap();
379         let timer_rx = timer.periodic(Duration::milliseconds(1000));
380
381         spawn(proc() {
382             let _ = timer_rx.recv_opt();
383         });
384
385         timer.oneshot(Duration::milliseconds(1));
386     }
387
388     #[test]
389     fn reset_doesnt_switch_tasks2() {
390         // similar test to the one above.
391         let mut timer = Timer::new().unwrap();
392         let timer_rx = timer.periodic(Duration::milliseconds(1000));
393
394         spawn(proc() {
395             let _ = timer_rx.recv_opt();
396         });
397
398         timer.sleep(Duration::milliseconds(1));
399     }
400
401     #[test]
402     fn sender_goes_away_oneshot() {
403         let rx = {
404             let mut timer = Timer::new().unwrap();
405             timer.oneshot(Duration::milliseconds(1000))
406         };
407         assert_eq!(rx.recv_opt(), Err(()));
408     }
409
410     #[test]
411     fn sender_goes_away_period() {
412         let rx = {
413             let mut timer = Timer::new().unwrap();
414             timer.periodic(Duration::milliseconds(1000))
415         };
416         assert_eq!(rx.recv_opt(), Err(()));
417     }
418
419     #[test]
420     fn receiver_goes_away_oneshot() {
421         let mut timer1 = Timer::new().unwrap();
422         timer1.oneshot(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));
427     }
428
429     #[test]
430     fn receiver_goes_away_period() {
431         let mut timer1 = Timer::new().unwrap();
432         timer1.periodic(Duration::milliseconds(1));
433         let mut timer2 = Timer::new().unwrap();
434         // while sleeping, the previous timer should fire and not have its
435         // callback do something terrible.
436         timer2.sleep(Duration::milliseconds(2));
437     }
438
439     #[test]
440     fn sleep_zero() {
441         let mut timer = Timer::new().unwrap();
442         timer.sleep(Duration::milliseconds(0));
443     }
444
445     #[test]
446     fn sleep_negative() {
447         let mut timer = Timer::new().unwrap();
448         timer.sleep(Duration::milliseconds(-1000000));
449     }
450
451     #[test]
452     fn oneshot_zero() {
453         let mut timer = Timer::new().unwrap();
454         let rx = timer.oneshot(Duration::milliseconds(0));
455         rx.recv();
456     }
457
458     #[test]
459     fn oneshot_negative() {
460         let mut timer = Timer::new().unwrap();
461         let rx = timer.oneshot(Duration::milliseconds(-1000000));
462         rx.recv();
463     }
464
465     #[test]
466     fn periodic_zero() {
467         let mut timer = Timer::new().unwrap();
468         let rx = timer.periodic(Duration::milliseconds(0));
469         rx.recv();
470         rx.recv();
471         rx.recv();
472         rx.recv();
473     }
474
475     #[test]
476     fn periodic_negative() {
477         let mut timer = Timer::new().unwrap();
478         let rx = timer.periodic(Duration::milliseconds(-1000000));
479         rx.recv();
480         rx.recv();
481         rx.recv();
482         rx.recv();
483     }
484
485 }