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