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-10-30 01:31:07 -05:00
|
|
|
use std::c_str::CString;
|
2013-12-12 19:47:48 -06:00
|
|
|
use std::cast;
|
2013-11-11 00:46:32 -06:00
|
|
|
use std::io::IoError;
|
|
|
|
use std::io::net::ip::SocketAddr;
|
|
|
|
use std::io::process::ProcessConfig;
|
|
|
|
use std::io::signal::Signum;
|
2013-12-12 19:47:48 -06:00
|
|
|
use std::io::{FileMode, FileAccess, Open, Append, Truncate, Read, Write,
|
|
|
|
ReadWrite, FileStat};
|
|
|
|
use std::io;
|
|
|
|
use std::libc::c_int;
|
|
|
|
use std::libc::{O_CREAT, O_APPEND, O_TRUNC, O_RDWR, O_RDONLY, O_WRONLY, S_IRUSR,
|
|
|
|
S_IWUSR};
|
|
|
|
use std::libc;
|
|
|
|
use std::path::Path;
|
|
|
|
use std::rt::rtio;
|
|
|
|
use std::rt::rtio::IoFactory;
|
2013-11-11 00:46:32 -06:00
|
|
|
use ai = std::io::net::addrinfo;
|
2013-10-22 17:13:18 -05:00
|
|
|
|
|
|
|
#[cfg(test)] use std::unstable::run_in_bare_thread;
|
|
|
|
|
2013-12-12 19:47:48 -06:00
|
|
|
use super::{uv_error_to_io_error, Loop};
|
2013-10-22 17:13:18 -05:00
|
|
|
|
2013-12-12 19:47:48 -06:00
|
|
|
use addrinfo::GetAddrInfoRequest;
|
|
|
|
use async::AsyncWatcher;
|
|
|
|
use file::{FsRequest, FileWatcher};
|
|
|
|
use queue::QueuePool;
|
|
|
|
use homing::HomeHandle;
|
|
|
|
use idle::IdleWatcher;
|
|
|
|
use net::{TcpWatcher, TcpListener, UdpWatcher};
|
|
|
|
use pipe::{PipeWatcher, PipeListener};
|
|
|
|
use process::Process;
|
|
|
|
use signal::SignalWatcher;
|
|
|
|
use timer::TimerWatcher;
|
|
|
|
use tty::TtyWatcher;
|
|
|
|
use uvll;
|
2013-10-22 17:13:18 -05:00
|
|
|
|
|
|
|
// Obviously an Event Loop is always home.
|
|
|
|
pub struct UvEventLoop {
|
|
|
|
priv uvio: UvIoFactory
|
|
|
|
}
|
|
|
|
|
|
|
|
impl UvEventLoop {
|
|
|
|
pub fn new() -> UvEventLoop {
|
2013-12-12 19:47:48 -06:00
|
|
|
let mut loop_ = Loop::new();
|
|
|
|
let handle_pool = QueuePool::new(&mut loop_);
|
2013-10-22 17:13:18 -05:00
|
|
|
UvEventLoop {
|
2013-12-12 19:47:48 -06:00
|
|
|
uvio: UvIoFactory {
|
|
|
|
loop_: loop_,
|
2013-12-15 02:56:29 -06:00
|
|
|
handle_pool: Some(handle_pool),
|
2013-12-12 19:47:48 -06:00
|
|
|
}
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Drop for UvEventLoop {
|
|
|
|
fn drop(&mut self) {
|
2013-12-15 02:56:29 -06:00
|
|
|
// Must first destroy the pool of handles before we destroy the loop
|
|
|
|
// because otherwise the contained async handle will be destroyed after
|
2013-12-16 00:20:53 -06:00
|
|
|
// the loop is free'd (use-after-free). We also must free the uv handle
|
|
|
|
// after the loop has been closed because during the closing of the loop
|
|
|
|
// the handle is required to be used apparently.
|
|
|
|
let handle = self.uvio.handle_pool.get_ref().handle();
|
2014-01-30 16:28:36 -06:00
|
|
|
drop(self.uvio.handle_pool.take());
|
2013-12-12 19:47:48 -06:00
|
|
|
self.uvio.loop_.close();
|
2013-12-16 00:20:53 -06:00
|
|
|
unsafe { uvll::free_handle(handle) }
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-12 19:47:48 -06:00
|
|
|
impl rtio::EventLoop for UvEventLoop {
|
2013-10-22 17:13:18 -05:00
|
|
|
fn run(&mut self) {
|
2013-12-12 19:47:48 -06:00
|
|
|
self.uvio.loop_.run();
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
|
|
|
|
2013-11-04 14:45:05 -06:00
|
|
|
fn callback(&mut self, f: proc()) {
|
2013-12-12 19:47:48 -06:00
|
|
|
IdleWatcher::onetime(&mut self.uvio.loop_, f);
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
|
|
|
|
2013-12-18 11:57:58 -06:00
|
|
|
fn pausable_idle_callback(&mut self, cb: ~rtio::Callback)
|
|
|
|
-> ~rtio::PausableIdleCallback
|
2013-12-12 19:47:48 -06:00
|
|
|
{
|
2013-12-18 11:57:58 -06:00
|
|
|
IdleWatcher::new(&mut self.uvio.loop_, cb) as ~rtio::PausableIdleCallback
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
|
|
|
|
2013-12-12 19:47:48 -06:00
|
|
|
fn remote_callback(&mut self, f: ~rtio::Callback) -> ~rtio::RemoteCallback {
|
|
|
|
~AsyncWatcher::new(&mut self.uvio.loop_, f) as ~rtio::RemoteCallback
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
|
|
|
|
2013-12-12 19:47:48 -06:00
|
|
|
fn io<'a>(&'a mut self) -> Option<&'a mut rtio::IoFactory> {
|
|
|
|
let factory = &mut self.uvio as &mut rtio::IoFactory;
|
2013-12-05 19:37:02 -06:00
|
|
|
Some(factory)
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-29 16:14:34 -05:00
|
|
|
#[cfg(not(test))]
|
2013-10-22 17:13:18 -05:00
|
|
|
#[lang = "event_loop_factory"]
|
2013-12-13 20:28:18 -06:00
|
|
|
pub fn new_loop() -> ~rtio::EventLoop {
|
2013-12-12 19:47:48 -06:00
|
|
|
~UvEventLoop::new() as ~rtio::EventLoop
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_callback_run_once() {
|
2013-12-13 13:30:59 -06:00
|
|
|
use std::rt::rtio::EventLoop;
|
2014-01-26 21:57:42 -06:00
|
|
|
run_in_bare_thread(proc() {
|
2013-10-22 17:13:18 -05:00
|
|
|
let mut event_loop = UvEventLoop::new();
|
|
|
|
let mut count = 0;
|
|
|
|
let count_ptr: *mut int = &mut count;
|
2014-01-26 21:57:42 -06:00
|
|
|
event_loop.callback(proc() {
|
2013-10-22 17:13:18 -05:00
|
|
|
unsafe { *count_ptr += 1 }
|
2014-01-26 21:57:42 -06:00
|
|
|
});
|
2013-10-22 17:13:18 -05:00
|
|
|
event_loop.run();
|
|
|
|
assert_eq!(count, 1);
|
2014-01-26 21:57:42 -06:00
|
|
|
});
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
|
|
|
|
2013-12-12 19:47:48 -06:00
|
|
|
pub struct UvIoFactory {
|
|
|
|
loop_: Loop,
|
2013-12-15 02:56:29 -06:00
|
|
|
priv handle_pool: Option<~QueuePool>,
|
2013-12-12 19:47:48 -06:00
|
|
|
}
|
2013-10-22 17:13:18 -05:00
|
|
|
|
|
|
|
impl UvIoFactory {
|
2013-12-12 19:47:48 -06:00
|
|
|
pub fn uv_loop<'a>(&mut self) -> *uvll::uv_loop_t { self.loop_.handle }
|
|
|
|
|
|
|
|
pub fn make_handle(&mut self) -> HomeHandle {
|
2013-12-18 12:14:44 -06:00
|
|
|
// It's understood by the homing code that the "local id" is just the
|
|
|
|
// pointer of the local I/O factory cast to a uint.
|
|
|
|
let id: uint = unsafe { cast::transmute_copy(&self) };
|
|
|
|
HomeHandle::new(id, &mut **self.handle_pool.get_mut_ref())
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl IoFactory for UvIoFactory {
|
|
|
|
// Connect to an address and return a new stream
|
|
|
|
// NB: This blocks the task waiting on the connection.
|
|
|
|
// It would probably be better to return a future
|
2013-11-05 02:27:41 -06:00
|
|
|
fn tcp_connect(&mut self, addr: SocketAddr)
|
2013-12-12 19:47:48 -06:00
|
|
|
-> Result<~rtio::RtioTcpStream, IoError>
|
2013-11-05 02:27:41 -06:00
|
|
|
{
|
2013-12-12 19:47:48 -06:00
|
|
|
match TcpWatcher::connect(self, addr) {
|
|
|
|
Ok(t) => Ok(~t as ~rtio::RtioTcpStream),
|
2013-11-05 02:27:41 -06:00
|
|
|
Err(e) => Err(uv_error_to_io_error(e)),
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-12 19:47:48 -06:00
|
|
|
fn tcp_bind(&mut self, addr: SocketAddr) -> Result<~rtio::RtioTcpListener, IoError> {
|
|
|
|
match TcpListener::bind(self, addr) {
|
|
|
|
Ok(t) => Ok(t as ~rtio::RtioTcpListener),
|
2013-11-05 02:27:41 -06:00
|
|
|
Err(e) => Err(uv_error_to_io_error(e)),
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-12 19:47:48 -06:00
|
|
|
fn udp_bind(&mut self, addr: SocketAddr) -> Result<~rtio::RtioUdpSocket, IoError> {
|
|
|
|
match UdpWatcher::bind(self, addr) {
|
|
|
|
Ok(u) => Ok(~u as ~rtio::RtioUdpSocket),
|
2013-11-05 02:27:41 -06:00
|
|
|
Err(e) => Err(uv_error_to_io_error(e)),
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-12 19:47:48 -06:00
|
|
|
fn timer_init(&mut self) -> Result<~rtio::RtioTimer, IoError> {
|
|
|
|
Ok(TimerWatcher::new(self) as ~rtio::RtioTimer)
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
|
|
|
|
2013-10-30 01:31:07 -05:00
|
|
|
fn get_host_addresses(&mut self, host: Option<&str>, servname: Option<&str>,
|
|
|
|
hint: Option<ai::Hint>) -> Result<~[ai::Info], IoError> {
|
2013-12-12 19:47:48 -06:00
|
|
|
let r = GetAddrInfoRequest::run(&self.loop_, host, servname, hint);
|
2013-11-05 00:52:33 -06:00
|
|
|
r.map_err(uv_error_to_io_error)
|
2013-10-30 01:31:07 -05:00
|
|
|
}
|
|
|
|
|
2013-11-04 23:08:25 -06:00
|
|
|
fn fs_from_raw_fd(&mut self, fd: c_int,
|
2013-12-12 19:47:48 -06:00
|
|
|
close: rtio::CloseBehavior) -> ~rtio::RtioFileStream {
|
|
|
|
~FileWatcher::new(self, fd, close) as ~rtio::RtioFileStream
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
fn fs_open(&mut self, path: &CString, fm: FileMode, fa: FileAccess)
|
2013-12-12 19:47:48 -06:00
|
|
|
-> Result<~rtio::RtioFileStream, IoError> {
|
2013-10-30 01:31:07 -05:00
|
|
|
let flags = match fm {
|
|
|
|
io::Open => 0,
|
|
|
|
io::Append => libc::O_APPEND,
|
|
|
|
io::Truncate => libc::O_TRUNC,
|
2013-10-22 17:13:18 -05:00
|
|
|
};
|
2013-10-30 01:31:07 -05:00
|
|
|
// Opening with a write permission must silently create the file.
|
|
|
|
let (flags, mode) = match fa {
|
|
|
|
io::Read => (flags | libc::O_RDONLY, 0),
|
|
|
|
io::Write => (flags | libc::O_WRONLY | libc::O_CREAT,
|
|
|
|
libc::S_IRUSR | libc::S_IWUSR),
|
|
|
|
io::ReadWrite => (flags | libc::O_RDWR | libc::O_CREAT,
|
|
|
|
libc::S_IRUSR | libc::S_IWUSR),
|
2013-10-22 17:13:18 -05:00
|
|
|
};
|
2013-11-04 23:08:25 -06:00
|
|
|
|
2013-12-12 19:47:48 -06:00
|
|
|
match FsRequest::open(self, path, flags as int, mode as int) {
|
|
|
|
Ok(fs) => Ok(~fs as ~rtio::RtioFileStream),
|
2013-11-04 23:08:25 -06:00
|
|
|
Err(e) => Err(uv_error_to_io_error(e))
|
|
|
|
}
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
fn fs_unlink(&mut self, path: &CString) -> Result<(), IoError> {
|
2013-12-12 19:47:48 -06:00
|
|
|
let r = FsRequest::unlink(&self.loop_, path);
|
2013-11-04 23:08:25 -06:00
|
|
|
r.map_err(uv_error_to_io_error)
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
2013-10-30 01:31:07 -05:00
|
|
|
fn fs_lstat(&mut self, path: &CString) -> Result<FileStat, IoError> {
|
2013-12-12 19:47:48 -06:00
|
|
|
let r = FsRequest::lstat(&self.loop_, path);
|
2013-11-04 23:08:25 -06:00
|
|
|
r.map_err(uv_error_to_io_error)
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
2013-10-30 01:31:07 -05:00
|
|
|
fn fs_stat(&mut self, path: &CString) -> Result<FileStat, IoError> {
|
2013-12-12 19:47:48 -06:00
|
|
|
let r = FsRequest::stat(&self.loop_, path);
|
2013-11-04 23:08:25 -06:00
|
|
|
r.map_err(uv_error_to_io_error)
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
2013-10-25 19:04:37 -05:00
|
|
|
fn fs_mkdir(&mut self, path: &CString,
|
|
|
|
perm: io::FilePermission) -> Result<(), IoError> {
|
2013-12-12 19:47:48 -06:00
|
|
|
let r = FsRequest::mkdir(&self.loop_, path, perm as c_int);
|
2013-11-04 23:08:25 -06:00
|
|
|
r.map_err(uv_error_to_io_error)
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
|
|
|
fn fs_rmdir(&mut self, path: &CString) -> Result<(), IoError> {
|
2013-12-12 19:47:48 -06:00
|
|
|
let r = FsRequest::rmdir(&self.loop_, path);
|
2013-11-04 23:08:25 -06:00
|
|
|
r.map_err(uv_error_to_io_error)
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
2013-10-25 18:50:08 -05:00
|
|
|
fn fs_rename(&mut self, path: &CString, to: &CString) -> Result<(), IoError> {
|
2013-12-12 19:47:48 -06:00
|
|
|
let r = FsRequest::rename(&self.loop_, path, to);
|
2013-11-04 23:08:25 -06:00
|
|
|
r.map_err(uv_error_to_io_error)
|
2013-10-25 18:50:08 -05:00
|
|
|
}
|
2013-10-25 19:04:37 -05:00
|
|
|
fn fs_chmod(&mut self, path: &CString,
|
|
|
|
perm: io::FilePermission) -> Result<(), IoError> {
|
2013-12-12 19:47:48 -06:00
|
|
|
let r = FsRequest::chmod(&self.loop_, path, perm as c_int);
|
2013-11-04 23:08:25 -06:00
|
|
|
r.map_err(uv_error_to_io_error)
|
2013-10-25 19:04:37 -05:00
|
|
|
}
|
2013-11-04 23:08:25 -06:00
|
|
|
fn fs_readdir(&mut self, path: &CString, flags: c_int)
|
|
|
|
-> Result<~[Path], IoError>
|
|
|
|
{
|
2013-12-12 19:47:48 -06:00
|
|
|
let r = FsRequest::readdir(&self.loop_, path, flags);
|
2013-11-04 23:08:25 -06:00
|
|
|
r.map_err(uv_error_to_io_error)
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
2013-10-30 01:31:07 -05:00
|
|
|
fn fs_link(&mut self, src: &CString, dst: &CString) -> Result<(), IoError> {
|
2013-12-12 19:47:48 -06:00
|
|
|
let r = FsRequest::link(&self.loop_, src, dst);
|
2013-11-04 23:08:25 -06:00
|
|
|
r.map_err(uv_error_to_io_error)
|
2013-10-30 01:31:07 -05:00
|
|
|
}
|
|
|
|
fn fs_symlink(&mut self, src: &CString, dst: &CString) -> Result<(), IoError> {
|
2013-12-12 19:47:48 -06:00
|
|
|
let r = FsRequest::symlink(&self.loop_, src, dst);
|
2013-11-04 23:08:25 -06:00
|
|
|
r.map_err(uv_error_to_io_error)
|
2013-10-30 01:31:07 -05:00
|
|
|
}
|
|
|
|
fn fs_chown(&mut self, path: &CString, uid: int, gid: int) -> Result<(), IoError> {
|
2013-12-12 19:47:48 -06:00
|
|
|
let r = FsRequest::chown(&self.loop_, path, uid, gid);
|
2013-11-04 23:08:25 -06:00
|
|
|
r.map_err(uv_error_to_io_error)
|
2013-10-30 01:31:07 -05:00
|
|
|
}
|
|
|
|
fn fs_readlink(&mut self, path: &CString) -> Result<Path, IoError> {
|
2013-12-12 19:47:48 -06:00
|
|
|
let r = FsRequest::readlink(&self.loop_, path);
|
2013-11-04 23:08:25 -06:00
|
|
|
r.map_err(uv_error_to_io_error)
|
2013-10-30 01:31:07 -05:00
|
|
|
}
|
2013-11-05 17:48:27 -06:00
|
|
|
fn fs_utime(&mut self, path: &CString, atime: u64, mtime: u64)
|
|
|
|
-> Result<(), IoError>
|
|
|
|
{
|
2013-12-12 19:47:48 -06:00
|
|
|
let r = FsRequest::utime(&self.loop_, path, atime, mtime);
|
2013-11-05 17:48:27 -06:00
|
|
|
r.map_err(uv_error_to_io_error)
|
|
|
|
}
|
2013-10-22 17:13:18 -05:00
|
|
|
|
|
|
|
fn spawn(&mut self, config: ProcessConfig)
|
2013-12-12 19:47:48 -06:00
|
|
|
-> Result<(~rtio::RtioProcess, ~[Option<~rtio::RtioPipe>]), IoError>
|
2013-10-22 17:13:18 -05:00
|
|
|
{
|
2013-12-12 19:47:48 -06:00
|
|
|
match Process::spawn(self, config) {
|
2013-11-01 12:26:43 -05:00
|
|
|
Ok((p, io)) => {
|
2013-12-12 19:47:48 -06:00
|
|
|
Ok((p as ~rtio::RtioProcess,
|
|
|
|
io.move_iter().map(|i| i.map(|p| ~p as ~rtio::RtioPipe)).collect()))
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
2013-11-01 12:26:43 -05:00
|
|
|
Err(e) => Err(uv_error_to_io_error(e)),
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-12 19:47:48 -06:00
|
|
|
fn unix_bind(&mut self, path: &CString) -> Result<~rtio::RtioUnixListener, IoError>
|
2013-11-04 18:42:05 -06:00
|
|
|
{
|
2013-12-12 19:47:48 -06:00
|
|
|
match PipeListener::bind(self, path) {
|
|
|
|
Ok(p) => Ok(p as ~rtio::RtioUnixListener),
|
2013-10-22 17:13:18 -05:00
|
|
|
Err(e) => Err(uv_error_to_io_error(e)),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-12 19:47:48 -06:00
|
|
|
fn unix_connect(&mut self, path: &CString) -> Result<~rtio::RtioPipe, IoError> {
|
|
|
|
match PipeWatcher::connect(self, path) {
|
|
|
|
Ok(p) => Ok(~p as ~rtio::RtioPipe),
|
2013-11-04 18:42:05 -06:00
|
|
|
Err(e) => Err(uv_error_to_io_error(e)),
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn tty_open(&mut self, fd: c_int, readable: bool)
|
2013-12-12 19:47:48 -06:00
|
|
|
-> Result<~rtio::RtioTTY, IoError> {
|
|
|
|
match TtyWatcher::new(self, fd, readable) {
|
|
|
|
Ok(tty) => Ok(~tty as ~rtio::RtioTTY),
|
2013-10-22 17:13:18 -05:00
|
|
|
Err(e) => Err(uv_error_to_io_error(e))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-12 19:47:48 -06:00
|
|
|
fn pipe_open(&mut self, fd: c_int) -> Result<~rtio::RtioPipe, IoError> {
|
|
|
|
match PipeWatcher::open(self, fd) {
|
|
|
|
Ok(s) => Ok(~s as ~rtio::RtioPipe),
|
2013-10-22 17:13:18 -05:00
|
|
|
Err(e) => Err(uv_error_to_io_error(e))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Rewrite channels yet again for upgradeability
This, the Nth rewrite of channels, is not a rewrite of the core logic behind
channels, but rather their API usage. In the past, we had the distinction
between oneshot, stream, and shared channels, but the most recent rewrite
dropped oneshots in favor of streams and shared channels.
This distinction of stream vs shared has shown that it's not quite what we'd
like either, and this moves the `std::comm` module in the direction of "one
channel to rule them all". There now remains only one Chan and one Port.
This new channel is actually a hybrid oneshot/stream/shared channel under the
hood in order to optimize for the use cases in question. Additionally, this also
reduces the cognitive burden of having to choose between a Chan or a SharedChan
in an API.
My simple benchmarks show no reduction in efficiency over the existing channels
today, and a 3x improvement in the oneshot case. I sadly don't have a
pre-last-rewrite compiler to test out the old old oneshots, but I would imagine
that the performance is comparable, but slightly slower (due to atomic reference
counting).
This commit also brings the bonus bugfix to channels that the pending queue of
messages are all dropped when a Port disappears rather then when both the Port
and the Chan disappear.
2014-01-08 20:31:48 -06:00
|
|
|
fn signal(&mut self, signum: Signum, channel: Chan<Signum>)
|
2013-12-12 19:47:48 -06:00
|
|
|
-> Result<~rtio::RtioSignal, IoError> {
|
|
|
|
match SignalWatcher::new(self, signum, channel) {
|
|
|
|
Ok(s) => Ok(s as ~rtio::RtioSignal),
|
2013-10-22 17:13:18 -05:00
|
|
|
Err(e) => Err(uv_error_to_io_error(e)),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|