]> git.lizzy.rs Git - rust.git/blob - src/librustuv/timer.rs
auto merge of #9613 : jld/rust/enum-discrim-size.r0, r=alexcrichton
[rust.git] / src / librustuv / 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 use std::libc::c_int;
12
13 use uvll;
14 use super::{Watcher, Loop, NativeHandle, TimerCallback, status_to_maybe_uv_error};
15
16 pub struct TimerWatcher(*uvll::uv_timer_t);
17 impl Watcher for TimerWatcher { }
18
19 impl TimerWatcher {
20     pub fn new(loop_: &mut Loop) -> TimerWatcher {
21         unsafe {
22             let handle = uvll::malloc_handle(uvll::UV_TIMER);
23             assert!(handle.is_not_null());
24             assert!(0 == uvll::timer_init(loop_.native_handle(), handle));
25             let mut watcher: TimerWatcher = NativeHandle::from_native_handle(handle);
26             watcher.install_watcher_data();
27             return watcher;
28         }
29     }
30
31     pub fn start(&mut self, timeout: u64, repeat: u64, cb: TimerCallback) {
32         {
33             let data = self.get_watcher_data();
34             data.timer_cb = Some(cb);
35         }
36
37         unsafe {
38             uvll::timer_start(self.native_handle(), timer_cb, timeout, repeat);
39         }
40
41         extern fn timer_cb(handle: *uvll::uv_timer_t, status: c_int) {
42             let mut watcher: TimerWatcher = NativeHandle::from_native_handle(handle);
43             let data = watcher.get_watcher_data();
44             let cb = data.timer_cb.get_ref();
45             let status = status_to_maybe_uv_error(status);
46             (*cb)(watcher, status);
47         }
48     }
49
50     pub fn stop(&mut self) {
51         unsafe {
52             uvll::timer_stop(self.native_handle());
53         }
54     }
55 }
56
57 impl NativeHandle<*uvll::uv_timer_t> for TimerWatcher {
58     fn from_native_handle(handle: *uvll::uv_timer_t) -> TimerWatcher {
59         TimerWatcher(handle)
60     }
61     fn native_handle(&self) -> *uvll::uv_idle_t {
62         match self { &TimerWatcher(ptr) => ptr }
63     }
64 }
65
66 #[cfg(test)]
67 mod test {
68     use super::*;
69     use Loop;
70     use std::unstable::run_in_bare_thread;
71
72     #[test]
73     fn smoke_test() {
74         do run_in_bare_thread {
75             let mut count = 0;
76             let count_ptr: *mut int = &mut count;
77             let mut loop_ = Loop::new();
78             let mut timer = TimerWatcher::new(&mut loop_);
79             do timer.start(10, 0) |timer, status| {
80                 assert!(status.is_none());
81                 unsafe { *count_ptr += 1 };
82                 timer.close(||());
83             }
84             loop_.run();
85             loop_.close();
86             assert!(count == 1);
87         }
88     }
89
90     #[test]
91     fn start_twice() {
92         do run_in_bare_thread {
93             let mut count = 0;
94             let count_ptr: *mut int = &mut count;
95             let mut loop_ = Loop::new();
96             let mut timer = TimerWatcher::new(&mut loop_);
97             do timer.start(10, 0) |timer, status| {
98                 let mut timer = timer;
99                 assert!(status.is_none());
100                 unsafe { *count_ptr += 1 };
101                 do timer.start(10, 0) |timer, status| {
102                     assert!(status.is_none());
103                     unsafe { *count_ptr += 1 };
104                     timer.close(||());
105                 }
106             }
107             loop_.run();
108             loop_.close();
109             assert!(count == 2);
110         }
111     }
112
113     #[test]
114     fn repeat_stop() {
115         do run_in_bare_thread {
116             let mut count = 0;
117             let count_ptr: *mut int = &mut count;
118             let mut loop_ = Loop::new();
119             let mut timer = TimerWatcher::new(&mut loop_);
120             do timer.start(1, 2) |timer, status| {
121                 assert!(status.is_none());
122                 unsafe {
123                     *count_ptr += 1;
124
125                     if *count_ptr == 10 {
126
127                         // Stop the timer and do something else
128                         let mut timer = timer;
129                         timer.stop();
130                         // Freeze timer so it can be captured
131                         let timer = timer;
132
133                         let mut loop_ = timer.event_loop();
134                         let mut timer2 = TimerWatcher::new(&mut loop_);
135                         do timer2.start(10, 0) |timer2, _| {
136
137                             *count_ptr += 1;
138
139                             timer2.close(||());
140
141                             // Restart the original timer
142                             let mut timer = timer;
143                             do timer.start(1, 0) |timer, _| {
144                                 *count_ptr += 1;
145                                 timer.close(||());
146                             }
147                         }
148                     }
149                 };
150             }
151             loop_.run();
152             loop_.close();
153             assert!(count == 12);
154         }
155     }
156
157 }