2013-10-22 17:13:18 -05:00
|
|
|
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
2013-11-04 14:45:05 -06:00
|
|
|
use std::cast;
|
|
|
|
use std::libc::{c_int, c_void};
|
2013-10-22 17:13:18 -05:00
|
|
|
|
|
|
|
use uvll;
|
2013-11-04 14:45:05 -06:00
|
|
|
use super::{Loop, UvHandle};
|
|
|
|
use std::rt::rtio::{Callback, PausibleIdleCallback};
|
2013-10-22 17:13:18 -05:00
|
|
|
|
2013-11-04 14:45:05 -06:00
|
|
|
pub struct IdleWatcher {
|
|
|
|
handle: *uvll::uv_idle_t,
|
|
|
|
idle_flag: bool,
|
|
|
|
closed: bool,
|
|
|
|
callback: Option<~Callback>,
|
|
|
|
}
|
2013-10-22 17:13:18 -05:00
|
|
|
|
|
|
|
impl IdleWatcher {
|
2013-11-04 14:45:05 -06:00
|
|
|
pub fn new(loop_: &mut Loop) -> ~IdleWatcher {
|
|
|
|
let handle = UvHandle::alloc(None::<IdleWatcher>, uvll::UV_IDLE);
|
|
|
|
assert_eq!(unsafe {
|
2013-11-04 16:03:32 -06:00
|
|
|
uvll::uv_idle_init(loop_.native_handle(), handle)
|
2013-11-04 14:45:05 -06:00
|
|
|
}, 0);
|
|
|
|
let me = ~IdleWatcher {
|
|
|
|
handle: handle,
|
|
|
|
idle_flag: false,
|
|
|
|
closed: false,
|
|
|
|
callback: None,
|
|
|
|
};
|
|
|
|
return me.install();
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn onetime(loop_: &mut Loop, f: proc()) {
|
|
|
|
let handle = UvHandle::alloc(None::<IdleWatcher>, uvll::UV_IDLE);
|
2013-10-22 17:13:18 -05:00
|
|
|
unsafe {
|
2013-11-04 16:03:32 -06:00
|
|
|
assert_eq!(uvll::uv_idle_init(loop_.native_handle(), handle), 0);
|
2013-11-04 14:45:05 -06:00
|
|
|
let data: *c_void = cast::transmute(~f);
|
|
|
|
uvll::set_data_for_uv_handle(handle, data);
|
2013-11-04 16:03:32 -06:00
|
|
|
assert_eq!(uvll::uv_idle_start(handle, onetime_cb), 0)
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
|
|
|
|
2013-11-04 14:45:05 -06:00
|
|
|
extern fn onetime_cb(handle: *uvll::uv_idle_t, status: c_int) {
|
|
|
|
assert_eq!(status, 0);
|
|
|
|
unsafe {
|
|
|
|
let data = uvll::get_data_for_uv_handle(handle);
|
|
|
|
let f: ~proc() = cast::transmute(data);
|
|
|
|
(*f)();
|
2013-11-04 16:03:32 -06:00
|
|
|
uvll::uv_idle_stop(handle);
|
|
|
|
uvll::uv_close(handle, close_cb);
|
2013-11-04 14:45:05 -06:00
|
|
|
}
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
|
|
|
|
2013-11-04 14:45:05 -06:00
|
|
|
extern fn close_cb(handle: *uvll::uv_handle_t) {
|
|
|
|
unsafe { uvll::free_handle(handle) }
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
|
|
|
}
|
2013-11-04 14:45:05 -06:00
|
|
|
}
|
2013-10-22 17:13:18 -05:00
|
|
|
|
2013-11-04 14:45:05 -06:00
|
|
|
impl PausibleIdleCallback for IdleWatcher {
|
|
|
|
fn start(&mut self, cb: ~Callback) {
|
|
|
|
assert!(self.callback.is_none());
|
|
|
|
self.callback = Some(cb);
|
2013-11-04 16:03:32 -06:00
|
|
|
assert_eq!(unsafe { uvll::uv_idle_start(self.handle, idle_cb) }, 0)
|
2013-11-04 14:45:05 -06:00
|
|
|
self.idle_flag = true;
|
|
|
|
}
|
|
|
|
fn pause(&mut self) {
|
|
|
|
if self.idle_flag == true {
|
2013-11-04 16:03:32 -06:00
|
|
|
assert_eq!(unsafe {uvll::uv_idle_stop(self.handle) }, 0);
|
2013-11-04 14:45:05 -06:00
|
|
|
self.idle_flag = false;
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
|
|
|
}
|
2013-11-04 14:45:05 -06:00
|
|
|
fn resume(&mut self) {
|
|
|
|
if self.idle_flag == false {
|
2013-11-04 16:03:32 -06:00
|
|
|
assert_eq!(unsafe { uvll::uv_idle_start(self.handle, idle_cb) }, 0)
|
2013-11-04 14:45:05 -06:00
|
|
|
self.idle_flag = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fn close(&mut self) {
|
|
|
|
self.pause();
|
|
|
|
if !self.closed {
|
|
|
|
self.closed = true;
|
|
|
|
self.close_async_();
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-04 14:45:05 -06:00
|
|
|
impl UvHandle<uvll::uv_idle_t> for IdleWatcher {
|
|
|
|
fn uv_handle(&self) -> *uvll::uv_idle_t { self.handle }
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
extern fn idle_cb(handle: *uvll::uv_idle_t, status: c_int) {
|
2013-11-04 14:45:05 -06:00
|
|
|
assert_eq!(status, 0);
|
|
|
|
let idle: &mut IdleWatcher = unsafe { UvHandle::from_uv_handle(&handle) };
|
|
|
|
assert!(idle.callback.is_some());
|
|
|
|
idle.callback.get_mut_ref().call();
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod test {
|
|
|
|
|
|
|
|
use Loop;
|
|
|
|
use super::*;
|
|
|
|
use std::unstable::run_in_bare_thread;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
#[ignore(reason = "valgrind - loop destroyed before watcher?")]
|
|
|
|
fn idle_new_then_close() {
|
|
|
|
do run_in_bare_thread {
|
|
|
|
let mut loop_ = Loop::new();
|
|
|
|
let idle_watcher = { IdleWatcher::new(&mut loop_) };
|
|
|
|
idle_watcher.close(||());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn idle_smoke_test() {
|
|
|
|
do run_in_bare_thread {
|
|
|
|
let mut loop_ = Loop::new();
|
|
|
|
let mut idle_watcher = { IdleWatcher::new(&mut loop_) };
|
|
|
|
let mut count = 10;
|
|
|
|
let count_ptr: *mut int = &mut count;
|
|
|
|
do idle_watcher.start |idle_watcher, status| {
|
|
|
|
let mut idle_watcher = idle_watcher;
|
|
|
|
assert!(status.is_none());
|
|
|
|
if unsafe { *count_ptr == 10 } {
|
|
|
|
idle_watcher.stop();
|
|
|
|
idle_watcher.close(||());
|
|
|
|
} else {
|
|
|
|
unsafe { *count_ptr = *count_ptr + 1; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
loop_.run();
|
|
|
|
loop_.close();
|
|
|
|
assert_eq!(count, 10);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn idle_start_stop_start() {
|
|
|
|
do run_in_bare_thread {
|
|
|
|
let mut loop_ = Loop::new();
|
|
|
|
let mut idle_watcher = { IdleWatcher::new(&mut loop_) };
|
|
|
|
do idle_watcher.start |idle_watcher, status| {
|
|
|
|
let mut idle_watcher = idle_watcher;
|
|
|
|
assert!(status.is_none());
|
|
|
|
idle_watcher.stop();
|
|
|
|
do idle_watcher.start |idle_watcher, status| {
|
|
|
|
assert!(status.is_none());
|
|
|
|
let mut idle_watcher = idle_watcher;
|
|
|
|
idle_watcher.stop();
|
|
|
|
idle_watcher.close(||());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
loop_.run();
|
|
|
|
loop_.close();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|