Skip to content

Commit 4724966

Browse files
committed
core::rt: Add uv timer bindings
1 parent 76e0977 commit 4724966

File tree

6 files changed

+207
-13
lines changed

6 files changed

+207
-13
lines changed

src/libcore/rt/local_sched.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,10 @@ pub unsafe fn unsafe_borrow_io() -> *mut IoFactoryObject {
9797
}
9898

9999
fn tls_key() -> tls::Key {
100-
maybe_tls_key().get()
100+
match maybe_tls_key() {
101+
Some(key) => key,
102+
None => abort!("runtime tls key not initialized")
103+
}
101104
}
102105

103106
fn maybe_tls_key() -> Option<tls::Key> {

src/libcore/rt/uv/mod.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ use rt::io::IoError;
5959
pub use self::file::FsRequest;
6060
pub use self::net::{StreamWatcher, TcpWatcher};
6161
pub use self::idle::IdleWatcher;
62+
pub use self::timer::TimerWatcher;
6263

6364
/// The implementation of `rtio` for libuv
6465
pub mod uvio;
@@ -69,6 +70,7 @@ pub mod uvll;
6970
pub mod file;
7071
pub mod net;
7172
pub mod idle;
73+
pub mod timer;
7274

7375
/// XXX: Loop(*handle) is buggy with destructors. Normal structs
7476
/// with dtors may not be destructured, but tuple structs can,
@@ -125,6 +127,7 @@ pub type NullCallback = ~fn();
125127
pub type IdleCallback = ~fn(IdleWatcher, Option<UvError>);
126128
pub type ConnectionCallback = ~fn(StreamWatcher, Option<UvError>);
127129
pub type FsCallback = ~fn(FsRequest, Option<UvError>);
130+
pub type TimerCallback = ~fn(TimerWatcher, Option<UvError>);
128131

129132

130133
/// Callbacks used by StreamWatchers, set as custom data on the foreign handle
@@ -134,7 +137,8 @@ struct WatcherData {
134137
connect_cb: Option<ConnectionCallback>,
135138
close_cb: Option<NullCallback>,
136139
alloc_cb: Option<AllocCallback>,
137-
idle_cb: Option<IdleCallback>
140+
idle_cb: Option<IdleCallback>,
141+
timer_cb: Option<TimerCallback>
138142
}
139143

140144
pub trait WatcherInterop {
@@ -162,7 +166,8 @@ impl<H, W: Watcher + NativeHandle<*H>> WatcherInterop for W {
162166
connect_cb: None,
163167
close_cb: None,
164168
alloc_cb: None,
165-
idle_cb: None
169+
idle_cb: None,
170+
timer_cb: None
166171
};
167172
let data = transmute::<~WatcherData, *c_void>(data);
168173
uvll::set_data_for_uv_handle(self.native_handle(), data);

src/libcore/rt/uv/timer.rs

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
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(handle, 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 mut data = watcher.get_watcher_data();
73+
data.close_cb.swap_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+
let mut timer = timer;
129+
assert!(status.is_none());
130+
unsafe { *count_ptr += 1 };
131+
timer.close(||());
132+
}
133+
}
134+
loop_.run();
135+
loop_.close();
136+
assert!(count == 2);
137+
}
138+
}
139+
140+
#[test]
141+
fn repeat_stop() {
142+
do run_in_bare_thread {
143+
let mut count = 0;
144+
let count_ptr: *mut int = &mut count;
145+
let mut loop_ = Loop::new();
146+
let mut timer = TimerWatcher::new(&mut loop_);
147+
do timer.start(10, 20) |timer, status| {
148+
assert!(status.is_none());
149+
unsafe {
150+
*count_ptr += 1;
151+
152+
if *count_ptr == 10 {
153+
154+
// Stop the timer and do something else
155+
let mut timer = timer;
156+
timer.stop();
157+
// Freeze timer so it can be captured
158+
let timer = timer;
159+
160+
let mut loop_ = timer.event_loop();
161+
let mut timer2 = TimerWatcher::new(&mut loop_);
162+
do timer2.start(10, 0) |timer2, status| {
163+
164+
unsafe { *count_ptr += 1; }
165+
166+
let mut timer2 = timer2;
167+
timer2.close(||());
168+
169+
// Restart the original timer
170+
let mut timer = timer;
171+
do timer.start(10, 0) |timer, status| {
172+
unsafe { *count_ptr += 1; }
173+
let mut timer = timer;
174+
timer.close(||());
175+
}
176+
}
177+
}
178+
};
179+
}
180+
loop_.run();
181+
loop_.close();
182+
assert!(count == 12);
183+
}
184+
}
185+
186+
}

src/libcore/rt/uv/uvll.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -268,9 +268,9 @@ pub unsafe fn buf_init(input: *u8, len: uint) -> uv_buf_t {
268268
pub unsafe fn timer_init(loop_ptr: *c_void, timer_ptr: *uv_timer_t) -> c_int {
269269
return rust_uv_timer_init(loop_ptr, timer_ptr);
270270
}
271-
pub unsafe fn timer_start(timer_ptr: *uv_timer_t, cb: *u8, timeout: uint,
272-
repeat: uint) -> c_int {
273-
return rust_uv_timer_start(timer_ptr, cb, timeout as c_uint, repeat as c_uint);
271+
pub unsafe fn timer_start(timer_ptr: *uv_timer_t, cb: *u8, timeout: u64,
272+
repeat: u64) -> c_int {
273+
return rust_uv_timer_start(timer_ptr, cb, timeout, repeat);
274274
}
275275
pub unsafe fn timer_stop(timer_ptr: *uv_timer_t) -> c_int {
276276
return rust_uv_timer_stop(timer_ptr);
@@ -431,8 +431,8 @@ extern {
431431
timer_handle: *uv_timer_t) -> c_int;
432432
fn rust_uv_timer_start(timer_handle: *uv_timer_t,
433433
cb: *u8,
434-
timeout: c_uint,
435-
repeat: c_uint) -> c_int;
434+
timeout: libc::uint64_t,
435+
repeat: libc::uint64_t) -> c_int;
436436
fn rust_uv_timer_stop(handle: *uv_timer_t) -> c_int;
437437

438438
fn rust_uv_malloc_buf_base_of(sug_size: size_t) -> *u8;

src/libstd/uv_ll.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -819,8 +819,8 @@ extern {
819819
unsafe fn rust_uv_timer_start(
820820
timer_handle: *uv_timer_t,
821821
cb: *u8,
822-
timeout: libc::c_uint,
823-
repeat: libc::c_uint) -> libc::c_int;
822+
timeout: libc::uint64_t,
823+
repeat: libc::uint64_t) -> libc::c_int;
824824
unsafe fn rust_uv_timer_stop(handle: *uv_timer_t) -> libc::c_int;
825825

826826
unsafe fn rust_uv_getaddrinfo(loop_ptr: *libc::c_void,
@@ -1084,8 +1084,8 @@ pub unsafe fn timer_init(loop_ptr: *libc::c_void,
10841084
}
10851085
pub unsafe fn timer_start(timer_ptr: *uv_timer_t, cb: *u8, timeout: uint,
10861086
repeat: uint) -> libc::c_int {
1087-
return rust_uv_timer_start(timer_ptr, cb, timeout as libc::c_uint,
1088-
repeat as libc::c_uint);
1087+
return rust_uv_timer_start(timer_ptr, cb, timeout as libc::uint64_t,
1088+
repeat as libc::uint64_t);
10891089
}
10901090
pub unsafe fn timer_stop(timer_ptr: *uv_timer_t) -> libc::c_int {
10911091
return rust_uv_timer_stop(timer_ptr);

src/rt/rust_uv.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ rust_uv_timer_init(uv_loop_t* loop, uv_timer_t* timer) {
229229

230230
extern "C" int
231231
rust_uv_timer_start(uv_timer_t* the_timer, uv_timer_cb cb,
232-
uint32_t timeout, uint32_t repeat) {
232+
int64_t timeout, int64_t repeat) {
233233
return uv_timer_start(the_timer, cb, timeout, repeat);
234234
}
235235

0 commit comments

Comments
 (0)