diff options
| author | Do Nhat Minh <mrordinaire@gmail.com> | 2013-09-19 12:03:50 +0800 |
|---|---|---|
| committer | Alex Crichton <alex@alexcrichton.com> | 2013-10-24 14:22:35 -0700 |
| commit | b5a02e07845b9fb4bc9b09909bd996c874fa3eed (patch) | |
| tree | 92d0986b83e14ca4b637cb933d11e46b272c5fc3 /src/libstd/rt/uv | |
| parent | 816e46dd633cf4cc5741dde6ce3bffd4a9ba67a7 (diff) | |
| download | rust-b5a02e07845b9fb4bc9b09909bd996c874fa3eed.tar.gz rust-b5a02e07845b9fb4bc9b09909bd996c874fa3eed.zip | |
wrapping libuv signal for use in Rust
descriptive names easier-to-use api reorganize and document
Diffstat (limited to 'src/libstd/rt/uv')
| -rw-r--r-- | src/libstd/rt/uv/mod.rs | 6 | ||||
| -rw-r--r-- | src/libstd/rt/uv/signal.rs | 100 | ||||
| -rw-r--r-- | src/libstd/rt/uv/uvio.rs | 45 | ||||
| -rw-r--r-- | src/libstd/rt/uv/uvll.rs | 24 |
4 files changed, 175 insertions, 0 deletions
diff --git a/src/libstd/rt/uv/mod.rs b/src/libstd/rt/uv/mod.rs index 88bb28d3763..c92a54425bf 100644 --- a/src/libstd/rt/uv/mod.rs +++ b/src/libstd/rt/uv/mod.rs @@ -48,6 +48,7 @@ use cast::transmute; use ptr::null; use unstable::finally::Finally; use rt::io::net::ip::SocketAddr; +use rt::io::signal::Signum; use rt::io::IoError; @@ -60,6 +61,7 @@ pub use self::timer::TimerWatcher; pub use self::async::AsyncWatcher; pub use self::process::Process; pub use self::pipe::Pipe; +pub use self::signal::SignalWatcher; /// The implementation of `rtio` for libuv pub mod uvio; @@ -76,6 +78,7 @@ pub mod addrinfo; pub mod process; pub mod pipe; pub mod tty; +pub mod signal; /// XXX: Loop(*handle) is buggy with destructors. Normal structs /// with dtors may not be destructured, but tuple structs can, @@ -146,6 +149,7 @@ pub type TimerCallback = ~fn(TimerWatcher, 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. @@ -162,6 +166,7 @@ struct WatcherData { udp_recv_cb: Option<UdpReceiveCallback>, udp_send_cb: Option<UdpSendCallback>, exit_cb: Option<ExitCallback>, + signal_cb: Option<SignalCallback>, } pub trait WatcherInterop { @@ -197,6 +202,7 @@ impl<H, W: Watcher + NativeHandle<*H>> WatcherInterop for W { udp_recv_cb: None, udp_send_cb: None, exit_cb: None, + signal_cb: None, }; let data = transmute::<~WatcherData, *c_void>(data); uvll::set_data_for_uv_handle(self.native_handle(), data); diff --git a/src/libstd/rt/uv/signal.rs b/src/libstd/rt/uv/signal.rs new file mode 100644 index 00000000000..70ea8e399d5 --- /dev/null +++ b/src/libstd/rt/uv/signal.rs @@ -0,0 +1,100 @@ +// 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. + +use cast; +use option::Some; +use libc::{c_int, c_void}; +use result::{Err, Ok, Result}; +use rt::io::IoError; +use rt::io::signal::Signum; +use rt::uv::{Loop, NativeHandle, NullCallback, SignalCallback, UvError, Watcher}; +use rt::uv::uv_error_to_io_error; +use rt::uv::uvll; + +pub struct SignalWatcher(*uvll::uv_signal_t); + +impl Watcher for SignalWatcher { } + +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::signal_init(loop_.native_handle(), handle)); + let mut watcher: SignalWatcher = NativeHandle::from_native_handle(handle); + watcher.install_watcher_data(); + return watcher; + } + } + + pub fn start(&mut self, signum: Signum, callback: SignalCallback) -> Result<(), IoError> { + { + let data = self.get_watcher_data(); + data.signal_cb = Some(callback); + } + + let ret = unsafe { + uvll::signal_start(self.native_handle(), signal_cb, signum as c_int) + }; + + return match ret { + 0 => Ok(()), + _ => Err(uv_error_to_io_error(UvError(ret))), + }; + + 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 i64) }); + } + } + + pub fn stop(&mut self) { + unsafe { + uvll::signal_stop(self.native_handle()); + } + } + + pub fn close(self, cb: NullCallback) { + let mut watcher = self; + { + let data = watcher.get_watcher_data(); + assert!(data.close_cb.is_none()); + data.close_cb = Some(cb); + } + + unsafe { + uvll::close(watcher.native_handle(), close_cb); + } + + extern fn close_cb(handle: *uvll::uv_signal_t) { + let mut watcher: SignalWatcher = NativeHandle::from_native_handle(handle); + { + let data = watcher.get_watcher_data(); + data.close_cb.take_unwrap()(); + } + watcher.drop_watcher_data(); + unsafe { + uvll::free_handle(handle as *c_void); + } + } + } +} + +impl NativeHandle<*uvll::uv_signal_t> for SignalWatcher { + fn from_native_handle(handle: *uvll::uv_signal_t) -> SignalWatcher { + SignalWatcher(handle) + } + + fn native_handle(&self) -> *uvll::uv_signal_t { + match self { &SignalWatcher(ptr) => ptr } + } +} diff --git a/src/libstd/rt/uv/uvio.rs b/src/libstd/rt/uv/uvio.rs index f12b1bce9e6..48f4dbe43d6 100644 --- a/src/libstd/rt/uv/uvio.rs +++ b/src/libstd/rt/uv/uvio.rs @@ -13,6 +13,7 @@ use cast::transmute; use cast; use cell::Cell; use clone::Clone; +use comm::{SendDeferred, SharedChan}; use libc::{c_int, c_uint, c_void, pid_t}; use ops::Drop; use option::*; @@ -40,6 +41,7 @@ use libc::{lseek, off_t, O_CREAT, O_APPEND, O_TRUNC, O_RDWR, O_RDONLY, O_WRONLY, use rt::io::{FileMode, FileAccess, OpenOrCreate, Open, Create, CreateOrTruncate, Append, Truncate, Read, Write, ReadWrite, FileStat}; +use rt::io::signal::Signum; use task; use ai = rt::io::net::addrinfo; @@ -861,6 +863,17 @@ impl IoFactory for UvIoFactory { Err(e) => Err(uv_error_to_io_error(e)) } } + + fn signal(&mut self, signum: Signum, channel: SharedChan<Signum>) + -> Result<~RtioSignalObject, 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), + Err(e) => Err(uv_error_to_io_error(e)), + } + } } pub struct UvTcpListener { @@ -1811,6 +1824,38 @@ 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) { + do self.home_for_io_with_sched |self_, scheduler| { + rtdebug!("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| { diff --git a/src/libstd/rt/uv/uvll.rs b/src/libstd/rt/uv/uvll.rs index f3e14dc314b..fa4083657d5 100644 --- a/src/libstd/rt/uv/uvll.rs +++ b/src/libstd/rt/uv/uvll.rs @@ -132,6 +132,7 @@ pub type uv_getaddrinfo_t = c_void; pub type uv_process_t = c_void; pub type uv_pipe_t = c_void; pub type uv_tty_t = c_void; +pub type uv_signal_t = c_void; pub struct uv_timespec_t { tv_sec: libc::c_long, @@ -219,6 +220,8 @@ pub type uv_getaddrinfo_cb = extern "C" fn(req: *uv_getaddrinfo_t, pub type uv_exit_cb = extern "C" fn(handle: *uv_process_t, exit_status: c_int, term_signal: c_int); +pub type uv_signal_cb = extern "C" fn(handle: *uv_signal_t, + signum: c_int); pub type sockaddr = c_void; pub type sockaddr_in = c_void; @@ -991,6 +994,21 @@ pub unsafe fn guess_handle(fd: c_int) -> uv_handle_type { rust_uv_guess_handle(fd) } +pub unsafe fn signal_init(loop_: *uv_loop_t, handle: *uv_signal_t) -> c_int { + #[fixed_stack_segment]; #[inline(never)]; + return rust_uv_signal_init(loop_, handle); +} +pub unsafe fn signal_start(handle: *uv_signal_t, + signal_cb: uv_signal_cb, + signum: c_int) -> c_int { + #[fixed_stack_segment]; #[inline(never)]; + return rust_uv_signal_start(handle, signal_cb, signum); +} +pub unsafe fn signal_stop(handle: *uv_signal_t) -> c_int { + #[fixed_stack_segment]; #[inline(never)]; + return rust_uv_signal_stop(handle); +} + pub struct uv_err_data { priv err_name: ~str, priv err_msg: ~str, @@ -1160,4 +1178,10 @@ extern { //#[rust_stack] pub fn rust_AI_NUMERICSERV() -> c_int; //#[rust_stack] pub fn rust_AI_PASSIVE() -> c_int; //#[rust_stack] pub fn rust_AI_V4MAPPED() -> c_int; + + fn rust_uv_signal_init(loop_: *uv_loop_t, handle: *uv_signal_t) -> c_int; + fn rust_uv_signal_start(handle: *uv_signal_t, + signal_cb: uv_signal_cb, + signum: c_int) -> c_int; + fn rust_uv_signal_stop(handle: *uv_signal_t) -> c_int; } |
