]> git.lizzy.rs Git - rust.git/blob - src/libstd/old_io/timer.rs
Auto merge of #23934 - lfairy:write-no-deref, r=alexcrichton
[rust.git] / src / libstd / old_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 //! Synchronous Timers
12 //!
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.
15
16 // FIXME: These functions take Durations but only pass ms to the backend impls.
17
18 use boxed::Box;
19 use sync::mpsc::{Receiver, Sender, channel};
20 use time::Duration;
21 use old_io::IoResult;
22 use sys::timer::Callback;
23 use sys::timer::Timer as TimerImp;
24
25 /// A synchronous timer object
26 ///
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.
30 ///
31 /// # Examples
32 ///
33 /// ```
34 /// # #![feature(old_io, std_misc)]
35 /// # fn foo() {
36 /// use std::old_io::Timer;
37 /// use std::time::Duration;
38 ///
39 /// let mut timer = Timer::new().unwrap();
40 /// timer.sleep(Duration::milliseconds(10)); // block the task for awhile
41 ///
42 /// let timeout = timer.oneshot(Duration::milliseconds(10));
43 /// // do some work
44 /// timeout.recv().unwrap(); // wait for the timeout to expire
45 ///
46 /// let periodic = timer.periodic(Duration::milliseconds(10));
47 /// loop {
48 ///     periodic.recv().unwrap();
49 ///     // this loop is only executed once every 10ms
50 /// }
51 /// # }
52 /// ```
53 ///
54 /// If only sleeping is necessary, then a convenience API is provided through
55 /// the `old_io::timer` module.
56 ///
57 /// ```
58 /// # #![feature(old_io, std_misc)]
59 /// # fn foo() {
60 /// use std::old_io::timer;
61 /// use std::time::Duration;
62 ///
63 /// // Put this task to sleep for 5 seconds
64 /// timer::sleep(Duration::seconds(5));
65 /// # }
66 /// ```
67 pub struct Timer {
68     inner: TimerImp,
69 }
70
71 struct TimerCallback { tx: Sender<()> }
72
73 /// Sleep the current task for the specified duration.
74 ///
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");
80
81     timer.sleep(duration)
82 }
83
84 impl 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 })
90     }
91
92     /// Blocks the current task for the specified duration.
93     ///
94     /// Note that this function will cause any other receivers for this timer to
95     /// be invalidated (the other end will be closed).
96     ///
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);
104     }
105
106     /// Creates a oneshot receiver which will have a notification sent when
107     /// the specified duration has elapsed.
108     ///
109     /// This does *not* block the current task, but instead returns immediately.
110     ///
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
116     /// fail.
117     ///
118     /// # Examples
119     ///
120     /// ```
121     /// # #![feature(old_io, std_misc)]
122     /// use std::old_io::Timer;
123     /// use std::time::Duration;
124     ///
125     /// let mut timer = Timer::new().unwrap();
126     /// let ten_milliseconds = timer.oneshot(Duration::milliseconds(10));
127     ///
128     /// for _ in 0..100 { /* do work */ }
129     ///
130     /// // blocks until 10 ms after the `oneshot` call
131     /// ten_milliseconds.recv().unwrap();
132     /// ```
133     ///
134     /// ```
135     /// # #![feature(old_io, std_misc)]
136     /// use std::old_io::Timer;
137     /// use std::time::Duration;
138     ///
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()
143     /// ```
144     ///
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 }));
152         } else {
153             tx.send(()).unwrap();
154         }
155         return rx
156     }
157
158     /// Creates a receiver which will have a continuous stream of notifications
159     /// being sent each time the specified duration has elapsed.
160     ///
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.
164     ///
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
170     /// fail.
171     ///
172     /// # Examples
173     ///
174     /// ```
175     /// # #![feature(old_io, std_misc)]
176     /// use std::old_io::Timer;
177     /// use std::time::Duration;
178     ///
179     /// let mut timer = Timer::new().unwrap();
180     /// let ten_milliseconds = timer.periodic(Duration::milliseconds(10));
181     ///
182     /// for _ in 0..100 { /* do work */ }
183     ///
184     /// // blocks until 10 ms after the `periodic` call
185     /// ten_milliseconds.recv().unwrap();
186     ///
187     /// for _ in 0..100 { /* do work */ }
188     ///
189     /// // blocks until 20 ms after the `periodic` call (*not* 10ms after the
190     /// // previous `recv`)
191     /// ten_milliseconds.recv().unwrap();
192     /// ```
193     ///
194     /// ```
195     /// # #![feature(old_io, std_misc)]
196     /// use std::old_io::Timer;
197     /// use std::time::Duration;
198     ///
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()
203     /// ```
204     ///
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 }));
215         return rx
216     }
217 }
218
219 impl Callback for TimerCallback {
220     fn call(&mut self) {
221         let _ = self.tx.send(());
222     }
223 }
224
225 fn in_ms_u64(d: Duration) -> u64 {
226     let ms = d.num_milliseconds();
227     if ms < 0 { return 0 };
228     return ms as u64;
229 }
230
231 #[cfg(test)]
232 mod test {
233     use super::Timer;
234     use thread;
235     use time::Duration;
236
237     #[test]
238     fn test_timer_send() {
239         let mut timer = Timer::new().unwrap();
240         thread::spawn(move || timer.sleep(Duration::milliseconds(1)));
241     }
242
243     #[test]
244     fn test_io_timer_sleep_simple() {
245         let mut timer = Timer::new().unwrap();
246         timer.sleep(Duration::milliseconds(1));
247     }
248
249     #[test]
250     fn test_io_timer_sleep_oneshot() {
251         let mut timer = Timer::new().unwrap();
252         timer.oneshot(Duration::milliseconds(1)).recv().unwrap();
253     }
254
255     #[test]
256     fn test_io_timer_sleep_oneshot_forget() {
257         let mut timer = Timer::new().unwrap();
258         timer.oneshot(Duration::milliseconds(100000000));
259     }
260
261     #[test]
262     fn oneshot_twice() {
263         let mut timer = Timer::new().unwrap();
264         let rx1 = timer.oneshot(Duration::milliseconds(10000));
265         let rx = timer.oneshot(Duration::milliseconds(1));
266         rx.recv().unwrap();
267         assert!(rx1.recv().is_err());
268     }
269
270     #[test]
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
275
276         assert!(rx.recv().is_err());
277     }
278
279     #[test]
280     fn test_io_timer_sleep_periodic() {
281         let mut timer = Timer::new().unwrap();
282         let rx = timer.periodic(Duration::milliseconds(1));
283         rx.recv().unwrap();
284         rx.recv().unwrap();
285         rx.recv().unwrap();
286     }
287
288     #[test]
289     fn test_io_timer_sleep_periodic_forget() {
290         let mut timer = Timer::new().unwrap();
291         timer.periodic(Duration::milliseconds(100000000));
292     }
293
294     #[test]
295     fn test_io_timer_sleep_standalone() {
296         super::sleep(Duration::milliseconds(1))
297     }
298
299     #[test]
300     fn oneshot() {
301         let mut timer = Timer::new().unwrap();
302
303         let rx = timer.oneshot(Duration::milliseconds(1));
304         rx.recv().unwrap();
305         assert!(rx.recv().is_err());
306
307         let rx = timer.oneshot(Duration::milliseconds(1));
308         rx.recv().unwrap();
309         assert!(rx.recv().is_err());
310     }
311
312     #[test]
313     fn test_override() {
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();
321     }
322
323     #[test]
324     fn period() {
325         let mut timer = Timer::new().unwrap();
326         let rx = timer.periodic(Duration::milliseconds(1));
327         rx.recv().unwrap();
328         rx.recv().unwrap();
329         let rx2 = timer.periodic(Duration::milliseconds(1));
330         rx2.recv().unwrap();
331         rx2.recv().unwrap();
332     }
333
334     #[test]
335     fn sleep() {
336         let mut timer = Timer::new().unwrap();
337         timer.sleep(Duration::milliseconds(1));
338         timer.sleep(Duration::milliseconds(1));
339     }
340
341     #[test]
342     #[should_panic]
343     fn oneshot_fail() {
344         let mut timer = Timer::new().unwrap();
345         let _rx = timer.oneshot(Duration::milliseconds(1));
346         panic!();
347     }
348
349     #[test]
350     #[should_panic]
351     fn period_fail() {
352         let mut timer = Timer::new().unwrap();
353         let _rx = timer.periodic(Duration::milliseconds(1));
354         panic!();
355     }
356
357     #[test]
358     #[should_panic]
359     fn normal_fail() {
360         let _timer = Timer::new().unwrap();
361         panic!();
362     }
363
364     #[test]
365     fn closing_channel_during_drop_doesnt_kill_everything() {
366         // see issue #10375
367         let mut timer = Timer::new().unwrap();
368         let timer_rx = timer.periodic(Duration::milliseconds(1000));
369
370         thread::spawn(move|| {
371             let _ = timer_rx.recv();
372         });
373
374         // when we drop the TimerWatcher we're going to destroy the channel,
375         // which must wake up the task on the other end
376     }
377
378     #[test]
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));
383
384         thread::spawn(move|| {
385             let _ = timer_rx.recv();
386         });
387
388         timer.oneshot(Duration::milliseconds(1));
389     }
390
391     #[test]
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));
396
397         thread::spawn(move|| {
398             let _ = timer_rx.recv();
399         });
400
401         timer.sleep(Duration::milliseconds(1));
402     }
403
404     #[test]
405     fn sender_goes_away_oneshot() {
406         let rx = {
407             let mut timer = Timer::new().unwrap();
408             timer.oneshot(Duration::milliseconds(1000))
409         };
410         assert!(rx.recv().is_err());
411     }
412
413     #[test]
414     fn sender_goes_away_period() {
415         let rx = {
416             let mut timer = Timer::new().unwrap();
417             timer.periodic(Duration::milliseconds(1000))
418         };
419         assert!(rx.recv().is_err());
420     }
421
422     #[test]
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));
430     }
431
432     #[test]
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));
440     }
441
442     #[test]
443     fn sleep_zero() {
444         let mut timer = Timer::new().unwrap();
445         timer.sleep(Duration::milliseconds(0));
446     }
447
448     #[test]
449     fn sleep_negative() {
450         let mut timer = Timer::new().unwrap();
451         timer.sleep(Duration::milliseconds(-1000000));
452     }
453
454     #[test]
455     fn oneshot_zero() {
456         let mut timer = Timer::new().unwrap();
457         let rx = timer.oneshot(Duration::milliseconds(0));
458         rx.recv().unwrap();
459     }
460
461     #[test]
462     fn oneshot_negative() {
463         let mut timer = Timer::new().unwrap();
464         let rx = timer.oneshot(Duration::milliseconds(-1000000));
465         rx.recv().unwrap();
466     }
467
468     #[test]
469     fn periodic_zero() {
470         let mut timer = Timer::new().unwrap();
471         let rx = timer.periodic(Duration::milliseconds(0));
472         rx.recv().unwrap();
473         rx.recv().unwrap();
474         rx.recv().unwrap();
475         rx.recv().unwrap();
476     }
477
478     #[test]
479     fn periodic_negative() {
480         let mut timer = Timer::new().unwrap();
481         let rx = timer.periodic(Duration::milliseconds(-1000000));
482         rx.recv().unwrap();
483         rx.recv().unwrap();
484         rx.recv().unwrap();
485         rx.recv().unwrap();
486     }
487
488 }