Migrate uv signal handling away from ~fn()

This commit is contained in:
Alex Crichton 2013-11-01 11:13:22 -07:00
parent ceab326e82
commit 9286d5113d
5 changed files with 56 additions and 87 deletions

View file

@ -191,7 +191,6 @@ pub type FsCallback = ~fn(&mut FsRequest, Option<UvError>);
pub type AsyncCallback = ~fn(AsyncWatcher, Option<UvError>);
pub type UdpReceiveCallback = ~fn(UdpWatcher, int, Buf, SocketAddr, uint, Option<UvError>);
pub type UdpSendCallback = ~fn(UdpWatcher, Option<UvError>);
pub type SignalCallback = ~fn(SignalWatcher, Signum);
/// Callbacks used by StreamWatchers, set as custom data on the foreign handle.
@ -206,7 +205,6 @@ struct WatcherData {
async_cb: Option<AsyncCallback>,
udp_recv_cb: Option<UdpReceiveCallback>,
udp_send_cb: Option<UdpSendCallback>,
signal_cb: Option<SignalCallback>,
}
pub trait WatcherInterop {

View file

@ -103,7 +103,6 @@ impl Process {
extern fn on_exit(handle: *uvll::uv_process_t,
exit_status: libc::c_int,
term_signal: libc::c_int) {
let handle = handle as *uvll::uv_handle_t;
let p: &mut Process = unsafe { UvHandle::from_uv_handle(&handle) };
assert!(p.exit_status.is_none());

View file

@ -8,65 +8,72 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::cast;
use std::libc::c_int;
use std::rt::io::signal::Signum;
use std::rt::sched::{SchedHandle, Scheduler};
use std::comm::{SharedChan, SendDeferred};
use std::rt::local::Local;
use std::rt::rtio::RtioSignal;
use super::{Loop, NativeHandle, SignalCallback, UvError, Watcher};
use super::{Loop, UvError, UvHandle};
use uvll;
use uvio::HomingIO;
pub struct SignalWatcher(*uvll::uv_signal_t);
pub struct SignalWatcher {
handle: *uvll::uv_signal_t,
home: SchedHandle,
impl Watcher for SignalWatcher { }
channel: SharedChan<Signum>,
signal: Signum,
}
impl SignalWatcher {
pub fn new(loop_: &mut Loop) -> SignalWatcher {
unsafe {
let handle = uvll::malloc_handle(uvll::UV_SIGNAL);
assert!(handle.is_not_null());
assert!(0 == uvll::uv_signal_init(loop_.native_handle(), handle));
let mut watcher: SignalWatcher = NativeHandle::from_native_handle(handle);
watcher.install_watcher_data();
return watcher;
}
}
pub fn new(loop_: &mut Loop, signum: Signum,
channel: SharedChan<Signum>) -> Result<~SignalWatcher, UvError> {
let handle = UvHandle::alloc(None::<SignalWatcher>, uvll::UV_SIGNAL);
assert_eq!(unsafe {
uvll::signal_init(loop_.native_handle(), handle)
}, 0);
pub fn start(&mut self, signum: Signum, callback: SignalCallback)
-> Result<(), UvError>
{
return unsafe {
match uvll::uv_signal_start(self.native_handle(), signal_cb,
signum as c_int) {
0 => {
let data = self.get_watcher_data();
data.signal_cb = Some(callback);
Ok(())
}
n => Err(UvError(n)),
match unsafe { uvll::signal_start(handle, signal_cb, signum as c_int) } {
0 => {
let s = ~SignalWatcher {
handle: handle,
home: get_handle_to_current_scheduler!(),
channel: channel,
signal: signum,
};
Ok(s.install())
}
n => {
unsafe { uvll::free_handle(handle) }
Err(UvError(n))
}
};
extern fn signal_cb(handle: *uvll::uv_signal_t, signum: c_int) {
let mut watcher: SignalWatcher = NativeHandle::from_native_handle(handle);
let data = watcher.get_watcher_data();
let cb = data.signal_cb.get_ref();
(*cb)(watcher, unsafe { cast::transmute(signum as int) });
}
}
pub fn stop(&mut self) {
unsafe {
uvll::uv_signal_stop(self.native_handle());
}
}
}
impl NativeHandle<*uvll::uv_signal_t> for SignalWatcher {
fn from_native_handle(handle: *uvll::uv_signal_t) -> SignalWatcher {
SignalWatcher(handle)
}
extern fn signal_cb(handle: *uvll::uv_signal_t, signum: c_int) {
let s: &mut SignalWatcher = unsafe { UvHandle::from_uv_handle(&handle) };
assert_eq!(signum as int, s.signal as int);
s.channel.send_deferred(s.signal);
}
fn native_handle(&self) -> *uvll::uv_signal_t {
match self { &SignalWatcher(ptr) => ptr }
impl HomingIO for SignalWatcher {
fn home<'r>(&'r mut self) -> &'r mut SchedHandle { &mut self.home }
}
impl UvHandle<uvll::uv_signal_t> for SignalWatcher {
fn uv_handle(&self) -> *uvll::uv_signal_t { self.handle }
}
impl RtioSignal for SignalWatcher {}
impl Drop for SignalWatcher {
fn drop(&mut self) {
do self.home_for_io |self_| {
self_.close_async_();
}
}
}

View file

@ -102,8 +102,7 @@ impl RtioTimer for TimerWatcher {
}
extern fn timer_cb(handle: *uvll::uv_timer_t, _status: c_int) {
let handle = handle as *uvll::uv_handle_t;
let timer : &mut TimerWatcher = unsafe { UvHandle::from_uv_handle(&handle) };
let timer: &mut TimerWatcher = unsafe { UvHandle::from_uv_handle(&handle) };
match timer.action.take_unwrap() {
WakeTask(task) => {

View file

@ -13,8 +13,8 @@ use std::cast::transmute;
use std::cast;
use std::cell::Cell;
use std::clone::Clone;
use std::comm::{SendDeferred, SharedChan, GenericChan};
use std::libc::{c_int, c_uint, c_void, pid_t};
use std::comm::{SharedChan, GenericChan};
use std::libc::{c_int, c_uint, c_void};
use std::ptr;
use std::str;
use std::rt::io;
@ -841,11 +841,8 @@ impl IoFactory for UvIoFactory {
fn signal(&mut self, signum: Signum, channel: SharedChan<Signum>)
-> Result<~RtioSignal, IoError> {
let watcher = SignalWatcher::new(self.uv_loop());
let home = get_handle_to_current_scheduler!();
let mut signal = ~UvSignal::new(watcher, home);
match signal.watcher.start(signum, |_, _| channel.send_deferred(signum)) {
Ok(()) => Ok(signal as ~RtioSignal),
match SignalWatcher::new(self.uv_loop(), signum, channel) {
Ok(s) => Ok(s as ~RtioSignal),
Err(e) => Err(uv_error_to_io_error(e)),
}
}
@ -1591,37 +1588,6 @@ impl RtioUnixAcceptor for UvUnixAcceptor {
}
}
pub struct UvSignal {
watcher: signal::SignalWatcher,
home: SchedHandle,
}
impl HomingIO for UvSignal {
fn home<'r>(&'r mut self) -> &'r mut SchedHandle { &mut self.home }
}
impl UvSignal {
fn new(w: signal::SignalWatcher, home: SchedHandle) -> UvSignal {
UvSignal { watcher: w, home: home }
}
}
impl RtioSignal for UvSignal {}
impl Drop for UvSignal {
fn drop(&mut self) {
let (_m, scheduler) = self.fire_homing_missile_sched();
uvdebug!("closing UvSignal");
do scheduler.deschedule_running_task_and_then |_, task| {
let task_cell = Cell::new(task);
do self.watcher.close {
let scheduler: ~Scheduler = Local::take();
scheduler.resume_blocked_task_immediately(task_cell.take());
}
}
}
}
// this function is full of lies
unsafe fn local_io() -> &'static mut IoFactory {
do Local::borrow |sched: &mut Scheduler| {