]> git.lizzy.rs Git - rust.git/blob - src/libstd/rt/io/timer.rs
Fix usage of libuv for windows
[rust.git] / src / libstd / rt / 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 ports which will receive notifications after a period of time.
17
18 # Example
19
20 ```rust
21
22 use std::rt::io::Timer;
23
24 let mut timer = Timer::new().unwrap();
25 timer.sleep(10); // block the task for awhile
26
27 let timeout = timer.oneshot(10);
28 // do some work
29 timeout.recv(); // wait for the timeout to expire
30
31 let periodic = timer.periodic(10);
32 loop {
33     periodic.recv();
34     // this loop is only executed once every 10ms
35 }
36
37 ```
38
39 */
40
41 use comm::{Port, PortOne};
42 use option::{Option, Some, None};
43 use result::{Ok, Err};
44 use rt::io::io_error;
45 use rt::rtio::{IoFactory, RtioTimer, with_local_io};
46
47 pub struct Timer {
48     priv obj: ~RtioTimer
49 }
50
51 /// Sleep the current task for `msecs` milliseconds.
52 pub fn sleep(msecs: u64) {
53     let mut timer = Timer::new().expect("timer::sleep: could not create a Timer");
54
55     timer.sleep(msecs)
56 }
57
58 impl Timer {
59     /// Creates a new timer which can be used to put the current task to sleep
60     /// for a number of milliseconds, or to possibly create channels which will
61     /// get notified after an amount of time has passed.
62     pub fn new() -> Option<Timer> {
63         do with_local_io |io| {
64             match io.timer_init() {
65                 Ok(t) => Some(Timer { obj: t }),
66                 Err(ioerr) => {
67                     rtdebug!("Timer::init: failed to init: {:?}", ioerr);
68                     io_error::cond.raise(ioerr);
69                     None
70                 }
71             }
72
73         }
74     }
75
76     /// Blocks the current task for `msecs` milliseconds.
77     ///
78     /// Note that this function will cause any other ports for this timer to be
79     /// invalidated (the other end will be closed).
80     pub fn sleep(&mut self, msecs: u64) {
81         self.obj.sleep(msecs);
82     }
83
84     /// Creates a oneshot port which will have a notification sent when `msecs`
85     /// milliseconds has elapsed. This does *not* block the current task, but
86     /// instead returns immediately.
87     ///
88     /// Note that this invalidates any previous port which has been created by
89     /// this timer, and that the returned port will be invalidated once the
90     /// timer is destroyed (when it falls out of scope).
91     pub fn oneshot(&mut self, msecs: u64) -> PortOne<()> {
92         self.obj.oneshot(msecs)
93     }
94
95     /// Creates a port which will have a continuous stream of notifications
96     /// being sent every `msecs` milliseconds. This does *not* block the
97     /// current task, but instead returns immediately. The first notification
98     /// will not be received immediately, but rather after `msec` milliseconds
99     /// have passed.
100     ///
101     /// Note that this invalidates any previous port which has been created by
102     /// this timer, and that the returned port will be invalidated once the
103     /// timer is destroyed (when it falls out of scope).
104     pub fn periodic(&mut self, msecs: u64) -> Port<()> {
105         self.obj.period(msecs)
106     }
107 }
108
109 #[cfg(test)]
110 mod test {
111     use prelude::*;
112     use super::*;
113     use rt::test::*;
114     use cell::Cell;
115     use task;
116
117     #[test]
118     fn test_io_timer_sleep_simple() {
119         do run_in_mt_newsched_task {
120             let mut timer = Timer::new().unwrap();
121             timer.sleep(1);
122         }
123     }
124
125     #[test]
126     fn test_io_timer_sleep_oneshot() {
127         do run_in_mt_newsched_task {
128             let mut timer = Timer::new().unwrap();
129             timer.oneshot(1).recv();
130         }
131     }
132
133     #[test]
134     fn test_io_timer_sleep_oneshot_forget() {
135         do run_in_mt_newsched_task {
136             let mut timer = Timer::new().unwrap();
137             timer.oneshot(100000000000);
138         }
139     }
140
141     #[test]
142     fn oneshot_twice() {
143         do run_in_mt_newsched_task {
144             let mut timer = Timer::new().unwrap();
145             let port1 = timer.oneshot(10000);
146             let port = timer.oneshot(1);
147             port.recv();
148             assert_eq!(port1.try_recv(), None);
149         }
150     }
151
152     #[test]
153     fn test_io_timer_oneshot_then_sleep() {
154         do run_in_mt_newsched_task {
155             let mut timer = Timer::new().unwrap();
156             let port = timer.oneshot(100000000000);
157             timer.sleep(1); // this should invalidate the port
158
159             assert_eq!(port.try_recv(), None);
160         }
161     }
162
163     #[test]
164     fn test_io_timer_sleep_periodic() {
165         do run_in_mt_newsched_task {
166             let mut timer = Timer::new().unwrap();
167             let port = timer.periodic(1);
168             port.recv();
169             port.recv();
170             port.recv();
171         }
172     }
173
174     #[test]
175     fn test_io_timer_sleep_periodic_forget() {
176         do run_in_mt_newsched_task {
177             let mut timer = Timer::new().unwrap();
178             timer.periodic(100000000000);
179         }
180     }
181
182     #[test]
183     fn test_io_timer_sleep_standalone() {
184         do run_in_mt_newsched_task {
185             sleep(1)
186         }
187     }
188 }