std: Deal with fallout of rtio changes
This commit is contained in:
parent
5ec36c358f
commit
da2293c6f6
21 changed files with 452 additions and 209 deletions
|
@ -27,10 +27,10 @@ use option::{Some, None, Option};
|
||||||
use owned::Box;
|
use owned::Box;
|
||||||
use result::{Ok, Err, Result};
|
use result::{Ok, Err, Result};
|
||||||
use rt::local::Local;
|
use rt::local::Local;
|
||||||
|
use rt::mutex::NativeMutex;
|
||||||
use rt::task::{Task, BlockedTask};
|
use rt::task::{Task, BlockedTask};
|
||||||
use rt::thread::Thread;
|
use rt::thread::Thread;
|
||||||
use sync::atomics;
|
use sync::atomics;
|
||||||
use unstable::mutex::NativeMutex;
|
|
||||||
|
|
||||||
use mpsc = sync::mpsc_queue;
|
use mpsc = sync::mpsc_queue;
|
||||||
|
|
||||||
|
|
|
@ -43,10 +43,10 @@ use owned::Box;
|
||||||
use ptr::RawPtr;
|
use ptr::RawPtr;
|
||||||
use result::{Result, Ok, Err};
|
use result::{Result, Ok, Err};
|
||||||
use rt::local::Local;
|
use rt::local::Local;
|
||||||
|
use rt::mutex::{NativeMutex, LockGuard};
|
||||||
use rt::task::{Task, BlockedTask};
|
use rt::task::{Task, BlockedTask};
|
||||||
use sync::atomics;
|
use sync::atomics;
|
||||||
use ty::Unsafe;
|
use ty::Unsafe;
|
||||||
use unstable::mutex::{NativeMutex, LockGuard};
|
|
||||||
use vec::Vec;
|
use vec::Vec;
|
||||||
|
|
||||||
pub struct Packet<T> {
|
pub struct Packet<T> {
|
||||||
|
|
|
@ -52,19 +52,22 @@ fs::unlink(&path);
|
||||||
use c_str::ToCStr;
|
use c_str::ToCStr;
|
||||||
use clone::Clone;
|
use clone::Clone;
|
||||||
use container::Container;
|
use container::Container;
|
||||||
|
use io;
|
||||||
use iter::Iterator;
|
use iter::Iterator;
|
||||||
use kinds::Send;
|
use kinds::Send;
|
||||||
use super::{Reader, Writer, Seek};
|
use libc;
|
||||||
use super::{SeekStyle, Read, Write, Open, IoError, Truncate};
|
|
||||||
use super::{FileMode, FileAccess, FileStat, IoResult, FilePermission};
|
|
||||||
use rt::rtio::{RtioFileStream, IoFactory, LocalIo};
|
|
||||||
use io;
|
|
||||||
use option::{Some, None, Option};
|
use option::{Some, None, Option};
|
||||||
use owned::Box;
|
use owned::Box;
|
||||||
use result::{Ok, Err};
|
|
||||||
use path;
|
|
||||||
use path::{Path, GenericPath};
|
use path::{Path, GenericPath};
|
||||||
|
use path;
|
||||||
|
use result::{Ok, Err};
|
||||||
|
use rt::rtio::{RtioFileStream, IoFactory, LocalIo};
|
||||||
|
use rt::rtio;
|
||||||
use slice::{OwnedVector, ImmutableVector};
|
use slice::{OwnedVector, ImmutableVector};
|
||||||
|
use super::UnstableFileStat;
|
||||||
|
use super::{FileMode, FileAccess, FileStat, IoResult, FilePermission};
|
||||||
|
use super::{Reader, Writer, Seek, Append, SeekCur, SeekEnd, SeekSet};
|
||||||
|
use super::{SeekStyle, Read, Write, ReadWrite, Open, IoError, Truncate};
|
||||||
use vec::Vec;
|
use vec::Vec;
|
||||||
|
|
||||||
/// Unconstrained file access type that exposes read and write operations
|
/// Unconstrained file access type that exposes read and write operations
|
||||||
|
@ -126,6 +129,16 @@ impl File {
|
||||||
pub fn open_mode(path: &Path,
|
pub fn open_mode(path: &Path,
|
||||||
mode: FileMode,
|
mode: FileMode,
|
||||||
access: FileAccess) -> IoResult<File> {
|
access: FileAccess) -> IoResult<File> {
|
||||||
|
let mode = match mode {
|
||||||
|
Open => rtio::Open,
|
||||||
|
Append => rtio::Append,
|
||||||
|
Truncate => rtio::Truncate,
|
||||||
|
};
|
||||||
|
let access = match access {
|
||||||
|
Read => rtio::Read,
|
||||||
|
Write => rtio::Write,
|
||||||
|
ReadWrite => rtio::ReadWrite,
|
||||||
|
};
|
||||||
LocalIo::maybe_raise(|io| {
|
LocalIo::maybe_raise(|io| {
|
||||||
io.fs_open(&path.to_c_str(), mode, access).map(|fd| {
|
io.fs_open(&path.to_c_str(), mode, access).map(|fd| {
|
||||||
File {
|
File {
|
||||||
|
@ -134,7 +147,7 @@ impl File {
|
||||||
last_nread: -1
|
last_nread: -1
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
}).map_err(IoError::from_rtio_error)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempts to open a file in read-only mode. This function is equivalent to
|
/// Attempts to open a file in read-only mode. This function is equivalent to
|
||||||
|
@ -184,7 +197,7 @@ impl File {
|
||||||
/// device. This will flush any internal buffers necessary to perform this
|
/// device. This will flush any internal buffers necessary to perform this
|
||||||
/// operation.
|
/// operation.
|
||||||
pub fn fsync(&mut self) -> IoResult<()> {
|
pub fn fsync(&mut self) -> IoResult<()> {
|
||||||
self.fd.fsync()
|
self.fd.fsync().map_err(IoError::from_rtio_error)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This function is similar to `fsync`, except that it may not synchronize
|
/// This function is similar to `fsync`, except that it may not synchronize
|
||||||
|
@ -192,7 +205,7 @@ impl File {
|
||||||
/// must synchronize content, but don't need the metadata on disk. The goal
|
/// must synchronize content, but don't need the metadata on disk. The goal
|
||||||
/// of this method is to reduce disk operations.
|
/// of this method is to reduce disk operations.
|
||||||
pub fn datasync(&mut self) -> IoResult<()> {
|
pub fn datasync(&mut self) -> IoResult<()> {
|
||||||
self.fd.datasync()
|
self.fd.datasync().map_err(IoError::from_rtio_error)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Either truncates or extends the underlying file, updating the size of
|
/// Either truncates or extends the underlying file, updating the size of
|
||||||
|
@ -204,7 +217,7 @@ impl File {
|
||||||
/// will be extended to `size` and have all of the intermediate data filled
|
/// will be extended to `size` and have all of the intermediate data filled
|
||||||
/// in with 0s.
|
/// in with 0s.
|
||||||
pub fn truncate(&mut self, size: i64) -> IoResult<()> {
|
pub fn truncate(&mut self, size: i64) -> IoResult<()> {
|
||||||
self.fd.truncate(size)
|
self.fd.truncate(size).map_err(IoError::from_rtio_error)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tests whether this stream has reached EOF.
|
/// Tests whether this stream has reached EOF.
|
||||||
|
@ -217,7 +230,10 @@ impl File {
|
||||||
|
|
||||||
/// Queries information about the underlying file.
|
/// Queries information about the underlying file.
|
||||||
pub fn stat(&mut self) -> IoResult<FileStat> {
|
pub fn stat(&mut self) -> IoResult<FileStat> {
|
||||||
self.fd.fstat()
|
match self.fd.fstat() {
|
||||||
|
Ok(s) => Ok(from_rtio(s)),
|
||||||
|
Err(e) => Err(IoError::from_rtio_error(e)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,7 +259,9 @@ impl File {
|
||||||
/// user lacks permissions to remove the file, or if some other filesystem-level
|
/// user lacks permissions to remove the file, or if some other filesystem-level
|
||||||
/// error occurs.
|
/// error occurs.
|
||||||
pub fn unlink(path: &Path) -> IoResult<()> {
|
pub fn unlink(path: &Path) -> IoResult<()> {
|
||||||
LocalIo::maybe_raise(|io| io.fs_unlink(&path.to_c_str()))
|
LocalIo::maybe_raise(|io| {
|
||||||
|
io.fs_unlink(&path.to_c_str())
|
||||||
|
}).map_err(IoError::from_rtio_error)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a path, query the file system to get information about a file,
|
/// Given a path, query the file system to get information about a file,
|
||||||
|
@ -268,9 +286,10 @@ pub fn unlink(path: &Path) -> IoResult<()> {
|
||||||
/// to perform a `stat` call on the given path or if there is no entry in the
|
/// to perform a `stat` call on the given path or if there is no entry in the
|
||||||
/// filesystem at the provided path.
|
/// filesystem at the provided path.
|
||||||
pub fn stat(path: &Path) -> IoResult<FileStat> {
|
pub fn stat(path: &Path) -> IoResult<FileStat> {
|
||||||
LocalIo::maybe_raise(|io| {
|
match LocalIo::maybe_raise(|io| io.fs_stat(&path.to_c_str())) {
|
||||||
io.fs_stat(&path.to_c_str())
|
Ok(s) => Ok(from_rtio(s)),
|
||||||
})
|
Err(e) => Err(IoError::from_rtio_error(e)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Perform the same operation as the `stat` function, except that this
|
/// Perform the same operation as the `stat` function, except that this
|
||||||
|
@ -282,9 +301,46 @@ pub fn stat(path: &Path) -> IoResult<FileStat> {
|
||||||
///
|
///
|
||||||
/// See `stat`
|
/// See `stat`
|
||||||
pub fn lstat(path: &Path) -> IoResult<FileStat> {
|
pub fn lstat(path: &Path) -> IoResult<FileStat> {
|
||||||
LocalIo::maybe_raise(|io| {
|
match LocalIo::maybe_raise(|io| io.fs_lstat(&path.to_c_str())) {
|
||||||
io.fs_lstat(&path.to_c_str())
|
Ok(s) => Ok(from_rtio(s)),
|
||||||
})
|
Err(e) => Err(IoError::from_rtio_error(e)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_rtio(s: rtio::FileStat) -> FileStat {
|
||||||
|
let rtio::FileStat {
|
||||||
|
size, kind, perm, created, modified,
|
||||||
|
accessed, device, inode, rdev,
|
||||||
|
nlink, uid, gid, blksize, blocks, flags, gen
|
||||||
|
} = s;
|
||||||
|
|
||||||
|
FileStat {
|
||||||
|
size: size,
|
||||||
|
kind: match (kind as libc::c_int) & libc::S_IFMT {
|
||||||
|
libc::S_IFREG => io::TypeFile,
|
||||||
|
libc::S_IFDIR => io::TypeDirectory,
|
||||||
|
libc::S_IFIFO => io::TypeNamedPipe,
|
||||||
|
libc::S_IFBLK => io::TypeBlockSpecial,
|
||||||
|
libc::S_IFLNK => io::TypeSymlink,
|
||||||
|
_ => io::TypeUnknown,
|
||||||
|
},
|
||||||
|
perm: FilePermission::from_bits_truncate(perm as u32),
|
||||||
|
created: created,
|
||||||
|
modified: modified,
|
||||||
|
accessed: accessed,
|
||||||
|
unstable: UnstableFileStat {
|
||||||
|
device: device,
|
||||||
|
inode: inode,
|
||||||
|
rdev: rdev,
|
||||||
|
nlink: nlink,
|
||||||
|
uid: uid,
|
||||||
|
gid: gid,
|
||||||
|
blksize: blksize,
|
||||||
|
blocks: blocks,
|
||||||
|
flags: flags,
|
||||||
|
gen: gen,
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Rename a file or directory to a new name.
|
/// Rename a file or directory to a new name.
|
||||||
|
@ -304,7 +360,9 @@ pub fn lstat(path: &Path) -> IoResult<FileStat> {
|
||||||
/// permissions to view the contents, or if some other intermittent I/O error
|
/// permissions to view the contents, or if some other intermittent I/O error
|
||||||
/// occurs.
|
/// occurs.
|
||||||
pub fn rename(from: &Path, to: &Path) -> IoResult<()> {
|
pub fn rename(from: &Path, to: &Path) -> IoResult<()> {
|
||||||
LocalIo::maybe_raise(|io| io.fs_rename(&from.to_c_str(), &to.to_c_str()))
|
LocalIo::maybe_raise(|io| {
|
||||||
|
io.fs_rename(&from.to_c_str(), &to.to_c_str())
|
||||||
|
}).map_err(IoError::from_rtio_error)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Copies the contents of one file to another. This function will also
|
/// Copies the contents of one file to another. This function will also
|
||||||
|
@ -382,25 +440,33 @@ pub fn copy(from: &Path, to: &Path) -> IoResult<()> {
|
||||||
/// Some possible error situations are not having the permission to
|
/// Some possible error situations are not having the permission to
|
||||||
/// change the attributes of a file or the file not existing.
|
/// change the attributes of a file or the file not existing.
|
||||||
pub fn chmod(path: &Path, mode: io::FilePermission) -> IoResult<()> {
|
pub fn chmod(path: &Path, mode: io::FilePermission) -> IoResult<()> {
|
||||||
LocalIo::maybe_raise(|io| io.fs_chmod(&path.to_c_str(), mode))
|
LocalIo::maybe_raise(|io| {
|
||||||
|
io.fs_chmod(&path.to_c_str(), mode.bits() as uint)
|
||||||
|
}).map_err(IoError::from_rtio_error)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Change the user and group owners of a file at the specified path.
|
/// Change the user and group owners of a file at the specified path.
|
||||||
pub fn chown(path: &Path, uid: int, gid: int) -> IoResult<()> {
|
pub fn chown(path: &Path, uid: int, gid: int) -> IoResult<()> {
|
||||||
LocalIo::maybe_raise(|io| io.fs_chown(&path.to_c_str(), uid, gid))
|
LocalIo::maybe_raise(|io| {
|
||||||
|
io.fs_chown(&path.to_c_str(), uid, gid)
|
||||||
|
}).map_err(IoError::from_rtio_error)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new hard link on the filesystem. The `dst` path will be a
|
/// Creates a new hard link on the filesystem. The `dst` path will be a
|
||||||
/// link pointing to the `src` path. Note that systems often require these
|
/// link pointing to the `src` path. Note that systems often require these
|
||||||
/// two paths to both be located on the same filesystem.
|
/// two paths to both be located on the same filesystem.
|
||||||
pub fn link(src: &Path, dst: &Path) -> IoResult<()> {
|
pub fn link(src: &Path, dst: &Path) -> IoResult<()> {
|
||||||
LocalIo::maybe_raise(|io| io.fs_link(&src.to_c_str(), &dst.to_c_str()))
|
LocalIo::maybe_raise(|io| {
|
||||||
|
io.fs_link(&src.to_c_str(), &dst.to_c_str())
|
||||||
|
}).map_err(IoError::from_rtio_error)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new symbolic link on the filesystem. The `dst` path will be a
|
/// Creates a new symbolic link on the filesystem. The `dst` path will be a
|
||||||
/// symlink pointing to the `src` path.
|
/// symlink pointing to the `src` path.
|
||||||
pub fn symlink(src: &Path, dst: &Path) -> IoResult<()> {
|
pub fn symlink(src: &Path, dst: &Path) -> IoResult<()> {
|
||||||
LocalIo::maybe_raise(|io| io.fs_symlink(&src.to_c_str(), &dst.to_c_str()))
|
LocalIo::maybe_raise(|io| {
|
||||||
|
io.fs_symlink(&src.to_c_str(), &dst.to_c_str())
|
||||||
|
}).map_err(IoError::from_rtio_error)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads a symlink, returning the file that the symlink points to.
|
/// Reads a symlink, returning the file that the symlink points to.
|
||||||
|
@ -412,7 +478,7 @@ pub fn symlink(src: &Path, dst: &Path) -> IoResult<()> {
|
||||||
pub fn readlink(path: &Path) -> IoResult<Path> {
|
pub fn readlink(path: &Path) -> IoResult<Path> {
|
||||||
LocalIo::maybe_raise(|io| {
|
LocalIo::maybe_raise(|io| {
|
||||||
Ok(Path::new(try!(io.fs_readlink(&path.to_c_str()))))
|
Ok(Path::new(try!(io.fs_readlink(&path.to_c_str()))))
|
||||||
})
|
}).map_err(IoError::from_rtio_error)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new, empty directory at the provided path
|
/// Create a new, empty directory at the provided path
|
||||||
|
@ -433,7 +499,9 @@ pub fn readlink(path: &Path) -> IoResult<Path> {
|
||||||
/// This call will return an error if the user lacks permissions to make a new
|
/// This call will return an error if the user lacks permissions to make a new
|
||||||
/// directory at the provided path, or if the directory already exists.
|
/// directory at the provided path, or if the directory already exists.
|
||||||
pub fn mkdir(path: &Path, mode: FilePermission) -> IoResult<()> {
|
pub fn mkdir(path: &Path, mode: FilePermission) -> IoResult<()> {
|
||||||
LocalIo::maybe_raise(|io| io.fs_mkdir(&path.to_c_str(), mode))
|
LocalIo::maybe_raise(|io| {
|
||||||
|
io.fs_mkdir(&path.to_c_str(), mode.bits() as uint)
|
||||||
|
}).map_err(IoError::from_rtio_error)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Remove an existing, empty directory
|
/// Remove an existing, empty directory
|
||||||
|
@ -453,7 +521,9 @@ pub fn mkdir(path: &Path, mode: FilePermission) -> IoResult<()> {
|
||||||
/// This call will return an error if the user lacks permissions to remove the
|
/// This call will return an error if the user lacks permissions to remove the
|
||||||
/// directory at the provided path, or if the directory isn't empty.
|
/// directory at the provided path, or if the directory isn't empty.
|
||||||
pub fn rmdir(path: &Path) -> IoResult<()> {
|
pub fn rmdir(path: &Path) -> IoResult<()> {
|
||||||
LocalIo::maybe_raise(|io| io.fs_rmdir(&path.to_c_str()))
|
LocalIo::maybe_raise(|io| {
|
||||||
|
io.fs_rmdir(&path.to_c_str())
|
||||||
|
}).map_err(IoError::from_rtio_error)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieve a vector containing all entries within a provided directory
|
/// Retrieve a vector containing all entries within a provided directory
|
||||||
|
@ -492,7 +562,7 @@ pub fn readdir(path: &Path) -> IoResult<Vec<Path>> {
|
||||||
Ok(try!(io.fs_readdir(&path.to_c_str(), 0)).move_iter().map(|a| {
|
Ok(try!(io.fs_readdir(&path.to_c_str(), 0)).move_iter().map(|a| {
|
||||||
Path::new(a)
|
Path::new(a)
|
||||||
}).collect())
|
}).collect())
|
||||||
})
|
}).map_err(IoError::from_rtio_error)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an iterator which will recursively walk the directory structure
|
/// Returns an iterator which will recursively walk the directory structure
|
||||||
|
@ -616,7 +686,9 @@ pub fn rmdir_recursive(path: &Path) -> IoResult<()> {
|
||||||
/// be in milliseconds.
|
/// be in milliseconds.
|
||||||
// FIXME(#10301) these arguments should not be u64
|
// FIXME(#10301) these arguments should not be u64
|
||||||
pub fn change_file_times(path: &Path, atime: u64, mtime: u64) -> IoResult<()> {
|
pub fn change_file_times(path: &Path, atime: u64, mtime: u64) -> IoResult<()> {
|
||||||
LocalIo::maybe_raise(|io| io.fs_utime(&path.to_c_str(), atime, mtime))
|
LocalIo::maybe_raise(|io| {
|
||||||
|
io.fs_utime(&path.to_c_str(), atime, mtime)
|
||||||
|
}).map_err(IoError::from_rtio_error)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Reader for File {
|
impl Reader for File {
|
||||||
|
@ -629,28 +701,35 @@ impl Reader for File {
|
||||||
_ => Ok(read as uint)
|
_ => Ok(read as uint)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Err(e) => Err(e),
|
Err(e) => Err(IoError::from_rtio_error(e)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Writer for File {
|
impl Writer for File {
|
||||||
fn write(&mut self, buf: &[u8]) -> IoResult<()> { self.fd.write(buf) }
|
fn write(&mut self, buf: &[u8]) -> IoResult<()> {
|
||||||
|
self.fd.write(buf).map_err(IoError::from_rtio_error)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Seek for File {
|
impl Seek for File {
|
||||||
fn tell(&self) -> IoResult<u64> {
|
fn tell(&self) -> IoResult<u64> {
|
||||||
self.fd.tell()
|
self.fd.tell().map_err(IoError::from_rtio_error)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()> {
|
fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()> {
|
||||||
|
let style = match style {
|
||||||
|
SeekSet => rtio::SeekSet,
|
||||||
|
SeekCur => rtio::SeekCur,
|
||||||
|
SeekEnd => rtio::SeekEnd,
|
||||||
|
};
|
||||||
match self.fd.seek(pos, style) {
|
match self.fd.seek(pos, style) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
// successful seek resets EOF indicator
|
// successful seek resets EOF indicator
|
||||||
self.last_nread = -1;
|
self.last_nread = -1;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Err(e) => Err(e),
|
Err(e) => Err(IoError::from_rtio_error(e)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -225,6 +225,7 @@ use option::{Option, Some, None};
|
||||||
use os;
|
use os;
|
||||||
use owned::Box;
|
use owned::Box;
|
||||||
use result::{Ok, Err, Result};
|
use result::{Ok, Err, Result};
|
||||||
|
use rt::rtio;
|
||||||
use slice::{Vector, MutableVector, ImmutableVector};
|
use slice::{Vector, MutableVector, ImmutableVector};
|
||||||
use str::{StrSlice, StrAllocating};
|
use str::{StrSlice, StrAllocating};
|
||||||
use str;
|
use str;
|
||||||
|
@ -323,6 +324,14 @@ impl IoError {
|
||||||
libc::ERROR_BROKEN_PIPE => (EndOfFile, "the pipe has ended"),
|
libc::ERROR_BROKEN_PIPE => (EndOfFile, "the pipe has ended"),
|
||||||
libc::ERROR_OPERATION_ABORTED =>
|
libc::ERROR_OPERATION_ABORTED =>
|
||||||
(TimedOut, "operation timed out"),
|
(TimedOut, "operation timed out"),
|
||||||
|
libc::WSAEINVAL => (InvalidInput, "invalid argument"),
|
||||||
|
libc::ERROR_CALL_NOT_IMPLEMENTED =>
|
||||||
|
(IoUnavailable, "function not implemented"),
|
||||||
|
libc::ERROR_CALL_NOT_IMPLEMENTED =>
|
||||||
|
(MismatchedFileTypeForOperation,
|
||||||
|
"invalid handle provided to function"),
|
||||||
|
libc::ERROR_NOTHING_TO_TERMINATE =>
|
||||||
|
(InvalidInput, "no process to kill"),
|
||||||
|
|
||||||
// libuv maps this error code to EISDIR. we do too. if it is found
|
// libuv maps this error code to EISDIR. we do too. if it is found
|
||||||
// to be incorrect, we can add in some more machinery to only
|
// to be incorrect, we can add in some more machinery to only
|
||||||
|
@ -351,9 +360,17 @@ impl IoError {
|
||||||
libc::EADDRINUSE => (ConnectionRefused, "address in use"),
|
libc::EADDRINUSE => (ConnectionRefused, "address in use"),
|
||||||
libc::ENOENT => (FileNotFound, "no such file or directory"),
|
libc::ENOENT => (FileNotFound, "no such file or directory"),
|
||||||
libc::EISDIR => (InvalidInput, "illegal operation on a directory"),
|
libc::EISDIR => (InvalidInput, "illegal operation on a directory"),
|
||||||
|
libc::ENOSYS => (IoUnavailable, "function not implemented"),
|
||||||
|
libc::EINVAL => (InvalidInput, "invalid argument"),
|
||||||
|
libc::ENOTTY =>
|
||||||
|
(MismatchedFileTypeForOperation,
|
||||||
|
"file descriptor is not a TTY"),
|
||||||
|
libc::ETIMEDOUT => (TimedOut, "operation timed out"),
|
||||||
|
libc::ECANCELED => (TimedOut, "operation aborted"),
|
||||||
|
|
||||||
// These two constants can have the same value on some systems, but
|
// These two constants can have the same value on some systems,
|
||||||
// different values on others, so we can't use a match clause
|
// but different values on others, so we can't use a match
|
||||||
|
// clause
|
||||||
x if x == libc::EAGAIN || x == libc::EWOULDBLOCK =>
|
x if x == libc::EAGAIN || x == libc::EWOULDBLOCK =>
|
||||||
(ResourceUnavailable, "resource temporarily unavailable"),
|
(ResourceUnavailable, "resource temporarily unavailable"),
|
||||||
|
|
||||||
|
@ -382,6 +399,17 @@ impl IoError {
|
||||||
pub fn last_error() -> IoError {
|
pub fn last_error() -> IoError {
|
||||||
IoError::from_errno(os::errno() as uint, true)
|
IoError::from_errno(os::errno() as uint, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn from_rtio_error(err: rtio::IoError) -> IoError {
|
||||||
|
let rtio::IoError { code, extra, detail } = err;
|
||||||
|
let mut ioerr = IoError::from_errno(code, false);
|
||||||
|
ioerr.detail = detail;
|
||||||
|
ioerr.kind = match ioerr.kind {
|
||||||
|
TimedOut if extra > 0 => ShortWrite(extra),
|
||||||
|
k => k,
|
||||||
|
};
|
||||||
|
return ioerr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Show for IoError {
|
impl fmt::Show for IoError {
|
||||||
|
|
|
@ -20,10 +20,12 @@ getaddrinfo()
|
||||||
#![allow(missing_doc)]
|
#![allow(missing_doc)]
|
||||||
|
|
||||||
use iter::Iterator;
|
use iter::Iterator;
|
||||||
use io::IoResult;
|
use io::{IoResult, IoError};
|
||||||
use io::net::ip::{SocketAddr, IpAddr};
|
use io::net::ip::{SocketAddr, IpAddr};
|
||||||
use option::{Option, Some, None};
|
use option::{Option, Some, None};
|
||||||
|
use result::{Ok, Err};
|
||||||
use rt::rtio::{IoFactory, LocalIo};
|
use rt::rtio::{IoFactory, LocalIo};
|
||||||
|
use rt::rtio;
|
||||||
use vec::Vec;
|
use vec::Vec;
|
||||||
|
|
||||||
/// Hints to the types of sockets that are desired when looking up hosts
|
/// Hints to the types of sockets that are desired when looking up hosts
|
||||||
|
@ -89,9 +91,34 @@ pub fn get_host_addresses(host: &str) -> IoResult<Vec<IpAddr>> {
|
||||||
///
|
///
|
||||||
/// FIXME: this is not public because the `Hint` structure is not ready for public
|
/// FIXME: this is not public because the `Hint` structure is not ready for public
|
||||||
/// consumption just yet.
|
/// consumption just yet.
|
||||||
|
#[allow(unused_variable)]
|
||||||
fn lookup(hostname: Option<&str>, servname: Option<&str>, hint: Option<Hint>)
|
fn lookup(hostname: Option<&str>, servname: Option<&str>, hint: Option<Hint>)
|
||||||
-> IoResult<Vec<Info>> {
|
-> IoResult<Vec<Info>> {
|
||||||
LocalIo::maybe_raise(|io| io.get_host_addresses(hostname, servname, hint))
|
let hint = hint.map(|Hint { family, socktype, protocol, flags }| {
|
||||||
|
rtio::AddrinfoHint {
|
||||||
|
family: family,
|
||||||
|
socktype: 0, // FIXME: this should use the above variable
|
||||||
|
protocol: 0, // FIXME: this should use the above variable
|
||||||
|
flags: flags,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
match LocalIo::maybe_raise(|io| {
|
||||||
|
io.get_host_addresses(hostname, servname, hint)
|
||||||
|
}) {
|
||||||
|
Ok(v) => Ok(v.move_iter().map(|info| {
|
||||||
|
Info {
|
||||||
|
address: SocketAddr {
|
||||||
|
ip: super::from_rtio(info.address.ip),
|
||||||
|
port: info.address.port,
|
||||||
|
},
|
||||||
|
family: info.family,
|
||||||
|
socktype: None, // FIXME: this should use the above variable
|
||||||
|
protocol: None, // FIXME: this should use the above variable
|
||||||
|
flags: info.flags,
|
||||||
|
}
|
||||||
|
}).collect()),
|
||||||
|
Err(e) => Err(IoError::from_rtio_error(e)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ignored on android since we cannot give tcp/ip
|
// Ignored on android since we cannot give tcp/ip
|
||||||
|
|
|
@ -10,6 +10,9 @@
|
||||||
|
|
||||||
//! Networking I/O
|
//! Networking I/O
|
||||||
|
|
||||||
|
use rt::rtio;
|
||||||
|
use self::ip::{Ipv4Addr, Ipv6Addr, IpAddr};
|
||||||
|
|
||||||
pub use self::addrinfo::get_host_addresses;
|
pub use self::addrinfo::get_host_addresses;
|
||||||
|
|
||||||
pub mod addrinfo;
|
pub mod addrinfo;
|
||||||
|
@ -18,3 +21,21 @@ pub mod udp;
|
||||||
pub mod ip;
|
pub mod ip;
|
||||||
// FIXME(#12093) - this should not be called unix
|
// FIXME(#12093) - this should not be called unix
|
||||||
pub mod unix;
|
pub mod unix;
|
||||||
|
|
||||||
|
fn to_rtio(ip: IpAddr) -> rtio::IpAddr {
|
||||||
|
match ip {
|
||||||
|
Ipv4Addr(a, b, c, d) => rtio::Ipv4Addr(a, b, c, d),
|
||||||
|
Ipv6Addr(a, b, c, d, e, f, g, h) => {
|
||||||
|
rtio::Ipv6Addr(a, b, c, d, e, f, g, h)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_rtio(ip: rtio::IpAddr) -> IpAddr {
|
||||||
|
match ip {
|
||||||
|
rtio::Ipv4Addr(a, b, c, d) => Ipv4Addr(a, b, c, d),
|
||||||
|
rtio::Ipv6Addr(a, b, c, d, e, f, g, h) => {
|
||||||
|
Ipv6Addr(a, b, c, d, e, f, g, h)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@ use option::{None, Some, Option};
|
||||||
use owned::Box;
|
use owned::Box;
|
||||||
use rt::rtio::{IoFactory, LocalIo, RtioSocket, RtioTcpListener};
|
use rt::rtio::{IoFactory, LocalIo, RtioSocket, RtioTcpListener};
|
||||||
use rt::rtio::{RtioTcpAcceptor, RtioTcpStream};
|
use rt::rtio::{RtioTcpAcceptor, RtioTcpStream};
|
||||||
|
use rt::rtio;
|
||||||
|
|
||||||
/// A structure which represents a TCP stream between a local socket and a
|
/// A structure which represents a TCP stream between a local socket and a
|
||||||
/// remote socket.
|
/// remote socket.
|
||||||
|
@ -67,22 +68,22 @@ impl TcpStream {
|
||||||
Some(addr) => vec!(addr),
|
Some(addr) => vec!(addr),
|
||||||
None => try!(get_host_addresses(host))
|
None => try!(get_host_addresses(host))
|
||||||
};
|
};
|
||||||
let mut err = IoError{
|
let mut err = IoError {
|
||||||
kind: ConnectionFailed,
|
kind: ConnectionFailed,
|
||||||
desc: "no addresses found for hostname",
|
desc: "no addresses found for hostname",
|
||||||
detail: None
|
detail: None
|
||||||
};
|
};
|
||||||
for address in addresses.iter() {
|
for addr in addresses.iter() {
|
||||||
let socket_addr = SocketAddr{ip: *address, port: port};
|
let addr = rtio::SocketAddr{ ip: super::to_rtio(*addr), port: port };
|
||||||
let result = LocalIo::maybe_raise(|io| {
|
let result = LocalIo::maybe_raise(|io| {
|
||||||
io.tcp_connect(socket_addr, None).map(TcpStream::new)
|
io.tcp_connect(addr, None).map(TcpStream::new)
|
||||||
});
|
});
|
||||||
match result {
|
match result {
|
||||||
Ok(stream) => {
|
Ok(stream) => {
|
||||||
return Ok(stream)
|
return Ok(stream)
|
||||||
}
|
}
|
||||||
Err(connect_err) => {
|
Err(connect_err) => {
|
||||||
err = connect_err
|
err = IoError::from_rtio_error(connect_err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -101,19 +102,31 @@ impl TcpStream {
|
||||||
#[experimental = "the timeout argument may eventually change types"]
|
#[experimental = "the timeout argument may eventually change types"]
|
||||||
pub fn connect_timeout(addr: SocketAddr,
|
pub fn connect_timeout(addr: SocketAddr,
|
||||||
timeout_ms: u64) -> IoResult<TcpStream> {
|
timeout_ms: u64) -> IoResult<TcpStream> {
|
||||||
|
let SocketAddr { ip, port } = addr;
|
||||||
|
let addr = rtio::SocketAddr { ip: super::to_rtio(ip), port: port };
|
||||||
LocalIo::maybe_raise(|io| {
|
LocalIo::maybe_raise(|io| {
|
||||||
io.tcp_connect(addr, Some(timeout_ms)).map(TcpStream::new)
|
io.tcp_connect(addr, Some(timeout_ms)).map(TcpStream::new)
|
||||||
})
|
}).map_err(IoError::from_rtio_error)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the socket address of the remote peer of this TCP connection.
|
/// Returns the socket address of the remote peer of this TCP connection.
|
||||||
pub fn peer_name(&mut self) -> IoResult<SocketAddr> {
|
pub fn peer_name(&mut self) -> IoResult<SocketAddr> {
|
||||||
self.obj.peer_name()
|
match self.obj.peer_name() {
|
||||||
|
Ok(rtio::SocketAddr { ip, port }) => {
|
||||||
|
Ok(SocketAddr { ip: super::from_rtio(ip), port: port })
|
||||||
|
}
|
||||||
|
Err(e) => Err(IoError::from_rtio_error(e)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the socket address of the local half of this TCP connection.
|
/// Returns the socket address of the local half of this TCP connection.
|
||||||
pub fn socket_name(&mut self) -> IoResult<SocketAddr> {
|
pub fn socket_name(&mut self) -> IoResult<SocketAddr> {
|
||||||
self.obj.socket_name()
|
match self.obj.socket_name() {
|
||||||
|
Ok(rtio::SocketAddr { ip, port }) => {
|
||||||
|
Ok(SocketAddr { ip: super::from_rtio(ip), port: port })
|
||||||
|
}
|
||||||
|
Err(e) => Err(IoError::from_rtio_error(e)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the nodelay flag on this connection to the boolean specified
|
/// Sets the nodelay flag on this connection to the boolean specified
|
||||||
|
@ -123,7 +136,7 @@ impl TcpStream {
|
||||||
self.obj.nodelay()
|
self.obj.nodelay()
|
||||||
} else {
|
} else {
|
||||||
self.obj.control_congestion()
|
self.obj.control_congestion()
|
||||||
}
|
}.map_err(IoError::from_rtio_error)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the keepalive timeout to the timeout specified.
|
/// Sets the keepalive timeout to the timeout specified.
|
||||||
|
@ -136,7 +149,7 @@ impl TcpStream {
|
||||||
match delay_in_seconds {
|
match delay_in_seconds {
|
||||||
Some(i) => self.obj.keepalive(i),
|
Some(i) => self.obj.keepalive(i),
|
||||||
None => self.obj.letdie(),
|
None => self.obj.letdie(),
|
||||||
}
|
}.map_err(IoError::from_rtio_error)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Closes the reading half of this connection.
|
/// Closes the reading half of this connection.
|
||||||
|
@ -168,7 +181,9 @@ impl TcpStream {
|
||||||
///
|
///
|
||||||
/// Note that this method affects all cloned handles associated with this
|
/// Note that this method affects all cloned handles associated with this
|
||||||
/// stream, not just this one handle.
|
/// stream, not just this one handle.
|
||||||
pub fn close_read(&mut self) -> IoResult<()> { self.obj.close_read() }
|
pub fn close_read(&mut self) -> IoResult<()> {
|
||||||
|
self.obj.close_read().map_err(IoError::from_rtio_error)
|
||||||
|
}
|
||||||
|
|
||||||
/// Closes the writing half of this connection.
|
/// Closes the writing half of this connection.
|
||||||
///
|
///
|
||||||
|
@ -177,7 +192,9 @@ impl TcpStream {
|
||||||
///
|
///
|
||||||
/// Note that this method affects all cloned handles associated with this
|
/// Note that this method affects all cloned handles associated with this
|
||||||
/// stream, not just this one handle.
|
/// stream, not just this one handle.
|
||||||
pub fn close_write(&mut self) -> IoResult<()> { self.obj.close_write() }
|
pub fn close_write(&mut self) -> IoResult<()> {
|
||||||
|
self.obj.close_write().map_err(IoError::from_rtio_error)
|
||||||
|
}
|
||||||
|
|
||||||
/// Sets a timeout, in milliseconds, for blocking operations on this stream.
|
/// Sets a timeout, in milliseconds, for blocking operations on this stream.
|
||||||
///
|
///
|
||||||
|
@ -261,11 +278,15 @@ impl Clone for TcpStream {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Reader for TcpStream {
|
impl Reader for TcpStream {
|
||||||
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> { self.obj.read(buf) }
|
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
|
||||||
|
self.obj.read(buf).map_err(IoError::from_rtio_error)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Writer for TcpStream {
|
impl Writer for TcpStream {
|
||||||
fn write(&mut self, buf: &[u8]) -> IoResult<()> { self.obj.write(buf) }
|
fn write(&mut self, buf: &[u8]) -> IoResult<()> {
|
||||||
|
self.obj.write(buf).map_err(IoError::from_rtio_error)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A structure representing a socket server. This listener is used to create a
|
/// A structure representing a socket server. This listener is used to create a
|
||||||
|
@ -319,10 +340,13 @@ impl TcpListener {
|
||||||
pub fn bind(addr: &str, port: u16) -> IoResult<TcpListener> {
|
pub fn bind(addr: &str, port: u16) -> IoResult<TcpListener> {
|
||||||
match FromStr::from_str(addr) {
|
match FromStr::from_str(addr) {
|
||||||
Some(ip) => {
|
Some(ip) => {
|
||||||
let socket_addr = SocketAddr{ip: ip, port: port};
|
let addr = rtio::SocketAddr{
|
||||||
|
ip: super::to_rtio(ip),
|
||||||
|
port: port,
|
||||||
|
};
|
||||||
LocalIo::maybe_raise(|io| {
|
LocalIo::maybe_raise(|io| {
|
||||||
io.tcp_bind(socket_addr).map(|l| TcpListener { obj: l })
|
io.tcp_bind(addr).map(|l| TcpListener { obj: l })
|
||||||
})
|
}).map_err(IoError::from_rtio_error)
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
Err(IoError{
|
Err(IoError{
|
||||||
|
@ -336,13 +360,21 @@ impl TcpListener {
|
||||||
|
|
||||||
/// Returns the local socket address of this listener.
|
/// Returns the local socket address of this listener.
|
||||||
pub fn socket_name(&mut self) -> IoResult<SocketAddr> {
|
pub fn socket_name(&mut self) -> IoResult<SocketAddr> {
|
||||||
self.obj.socket_name()
|
match self.obj.socket_name() {
|
||||||
|
Ok(rtio::SocketAddr { ip, port }) => {
|
||||||
|
Ok(SocketAddr { ip: super::from_rtio(ip), port: port })
|
||||||
|
}
|
||||||
|
Err(e) => Err(IoError::from_rtio_error(e)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Listener<TcpStream, TcpAcceptor> for TcpListener {
|
impl Listener<TcpStream, TcpAcceptor> for TcpListener {
|
||||||
fn listen(self) -> IoResult<TcpAcceptor> {
|
fn listen(self) -> IoResult<TcpAcceptor> {
|
||||||
self.obj.listen().map(|acceptor| TcpAcceptor { obj: acceptor })
|
match self.obj.listen() {
|
||||||
|
Ok(acceptor) => Ok(TcpAcceptor { obj: acceptor }),
|
||||||
|
Err(e) => Err(IoError::from_rtio_error(e)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -403,7 +435,10 @@ impl TcpAcceptor {
|
||||||
|
|
||||||
impl Acceptor<TcpStream> for TcpAcceptor {
|
impl Acceptor<TcpStream> for TcpAcceptor {
|
||||||
fn accept(&mut self) -> IoResult<TcpStream> {
|
fn accept(&mut self) -> IoResult<TcpStream> {
|
||||||
self.obj.accept().map(TcpStream::new)
|
match self.obj.accept(){
|
||||||
|
Ok(s) => Ok(TcpStream::new(s)),
|
||||||
|
Err(e) => Err(IoError::from_rtio_error(e)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,12 +17,13 @@
|
||||||
|
|
||||||
use clone::Clone;
|
use clone::Clone;
|
||||||
use io::net::ip::{SocketAddr, IpAddr};
|
use io::net::ip::{SocketAddr, IpAddr};
|
||||||
use io::{Reader, Writer, IoResult};
|
use io::{Reader, Writer, IoResult, IoError};
|
||||||
use kinds::Send;
|
use kinds::Send;
|
||||||
use owned::Box;
|
use owned::Box;
|
||||||
use option::Option;
|
use option::Option;
|
||||||
use result::{Ok, Err};
|
use result::{Ok, Err};
|
||||||
use rt::rtio::{RtioSocket, RtioUdpSocket, IoFactory, LocalIo};
|
use rt::rtio::{RtioSocket, RtioUdpSocket, IoFactory, LocalIo};
|
||||||
|
use rt::rtio;
|
||||||
|
|
||||||
/// A User Datagram Protocol socket.
|
/// A User Datagram Protocol socket.
|
||||||
///
|
///
|
||||||
|
@ -62,22 +63,32 @@ pub struct UdpSocket {
|
||||||
impl UdpSocket {
|
impl UdpSocket {
|
||||||
/// Creates a UDP socket from the given socket address.
|
/// Creates a UDP socket from the given socket address.
|
||||||
pub fn bind(addr: SocketAddr) -> IoResult<UdpSocket> {
|
pub fn bind(addr: SocketAddr) -> IoResult<UdpSocket> {
|
||||||
|
let SocketAddr { ip, port } = addr;
|
||||||
LocalIo::maybe_raise(|io| {
|
LocalIo::maybe_raise(|io| {
|
||||||
|
let addr = rtio::SocketAddr { ip: super::to_rtio(ip), port: port };
|
||||||
io.udp_bind(addr).map(|s| UdpSocket { obj: s })
|
io.udp_bind(addr).map(|s| UdpSocket { obj: s })
|
||||||
})
|
}).map_err(IoError::from_rtio_error)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Receives data from the socket. On success, returns the number of bytes
|
/// Receives data from the socket. On success, returns the number of bytes
|
||||||
/// read and the address from whence the data came.
|
/// read and the address from whence the data came.
|
||||||
pub fn recvfrom(&mut self, buf: &mut [u8])
|
pub fn recvfrom(&mut self, buf: &mut [u8])
|
||||||
-> IoResult<(uint, SocketAddr)> {
|
-> IoResult<(uint, SocketAddr)> {
|
||||||
self.obj.recvfrom(buf)
|
match self.obj.recvfrom(buf) {
|
||||||
|
Ok((amt, rtio::SocketAddr { ip, port })) => {
|
||||||
|
Ok((amt, SocketAddr { ip: super::from_rtio(ip), port: port }))
|
||||||
|
}
|
||||||
|
Err(e) => Err(IoError::from_rtio_error(e)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sends data on the socket to the given address. Returns nothing on
|
/// Sends data on the socket to the given address. Returns nothing on
|
||||||
/// success.
|
/// success.
|
||||||
pub fn sendto(&mut self, buf: &[u8], dst: SocketAddr) -> IoResult<()> {
|
pub fn sendto(&mut self, buf: &[u8], dst: SocketAddr) -> IoResult<()> {
|
||||||
self.obj.sendto(buf, dst)
|
self.obj.sendto(buf, rtio::SocketAddr {
|
||||||
|
ip: super::to_rtio(dst.ip),
|
||||||
|
port: dst.port,
|
||||||
|
}).map_err(IoError::from_rtio_error)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a `UdpStream`, which allows use of the `Reader` and `Writer`
|
/// Creates a `UdpStream`, which allows use of the `Reader` and `Writer`
|
||||||
|
@ -95,19 +106,24 @@ impl UdpSocket {
|
||||||
|
|
||||||
/// Returns the socket address that this socket was created from.
|
/// Returns the socket address that this socket was created from.
|
||||||
pub fn socket_name(&mut self) -> IoResult<SocketAddr> {
|
pub fn socket_name(&mut self) -> IoResult<SocketAddr> {
|
||||||
self.obj.socket_name()
|
match self.obj.socket_name() {
|
||||||
|
Ok(a) => Ok(SocketAddr { ip: super::from_rtio(a.ip), port: a.port }),
|
||||||
|
Err(e) => Err(IoError::from_rtio_error(e))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Joins a multicast IP address (becomes a member of it)
|
/// Joins a multicast IP address (becomes a member of it)
|
||||||
#[experimental]
|
#[experimental]
|
||||||
pub fn join_multicast(&mut self, multi: IpAddr) -> IoResult<()> {
|
pub fn join_multicast(&mut self, multi: IpAddr) -> IoResult<()> {
|
||||||
self.obj.join_multicast(multi)
|
let e = self.obj.join_multicast(super::to_rtio(multi));
|
||||||
|
e.map_err(IoError::from_rtio_error)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Leaves a multicast IP address (drops membership from it)
|
/// Leaves a multicast IP address (drops membership from it)
|
||||||
#[experimental]
|
#[experimental]
|
||||||
pub fn leave_multicast(&mut self, multi: IpAddr) -> IoResult<()> {
|
pub fn leave_multicast(&mut self, multi: IpAddr) -> IoResult<()> {
|
||||||
self.obj.leave_multicast(multi)
|
let e = self.obj.leave_multicast(super::to_rtio(multi));
|
||||||
|
e.map_err(IoError::from_rtio_error)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the multicast loop flag to the specified value
|
/// Set the multicast loop flag to the specified value
|
||||||
|
@ -119,19 +135,19 @@ impl UdpSocket {
|
||||||
self.obj.loop_multicast_locally()
|
self.obj.loop_multicast_locally()
|
||||||
} else {
|
} else {
|
||||||
self.obj.dont_loop_multicast_locally()
|
self.obj.dont_loop_multicast_locally()
|
||||||
}
|
}.map_err(IoError::from_rtio_error)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the multicast TTL
|
/// Sets the multicast TTL
|
||||||
#[experimental]
|
#[experimental]
|
||||||
pub fn set_multicast_ttl(&mut self, ttl: int) -> IoResult<()> {
|
pub fn set_multicast_ttl(&mut self, ttl: int) -> IoResult<()> {
|
||||||
self.obj.multicast_time_to_live(ttl)
|
self.obj.multicast_time_to_live(ttl).map_err(IoError::from_rtio_error)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets this socket's TTL
|
/// Sets this socket's TTL
|
||||||
#[experimental]
|
#[experimental]
|
||||||
pub fn set_ttl(&mut self, ttl: int) -> IoResult<()> {
|
pub fn set_ttl(&mut self, ttl: int) -> IoResult<()> {
|
||||||
self.obj.time_to_live(ttl)
|
self.obj.time_to_live(ttl).map_err(IoError::from_rtio_error)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the broadcast flag on or off
|
/// Sets the broadcast flag on or off
|
||||||
|
@ -141,7 +157,7 @@ impl UdpSocket {
|
||||||
self.obj.hear_broadcasts()
|
self.obj.hear_broadcasts()
|
||||||
} else {
|
} else {
|
||||||
self.obj.ignore_broadcasts()
|
self.obj.ignore_broadcasts()
|
||||||
}
|
}.map_err(IoError::from_rtio_error)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the read/write timeout for this socket.
|
/// Sets the read/write timeout for this socket.
|
||||||
|
|
|
@ -28,7 +28,7 @@ use prelude::*;
|
||||||
|
|
||||||
use c_str::ToCStr;
|
use c_str::ToCStr;
|
||||||
use clone::Clone;
|
use clone::Clone;
|
||||||
use io::{Listener, Acceptor, Reader, Writer, IoResult};
|
use io::{Listener, Acceptor, Reader, Writer, IoResult, IoError};
|
||||||
use kinds::Send;
|
use kinds::Send;
|
||||||
use owned::Box;
|
use owned::Box;
|
||||||
use rt::rtio::{IoFactory, LocalIo, RtioUnixListener};
|
use rt::rtio::{IoFactory, LocalIo, RtioUnixListener};
|
||||||
|
@ -58,7 +58,7 @@ impl UnixStream {
|
||||||
pub fn connect<P: ToCStr>(path: &P) -> IoResult<UnixStream> {
|
pub fn connect<P: ToCStr>(path: &P) -> IoResult<UnixStream> {
|
||||||
LocalIo::maybe_raise(|io| {
|
LocalIo::maybe_raise(|io| {
|
||||||
io.unix_connect(&path.to_c_str(), None).map(|p| UnixStream { obj: p })
|
io.unix_connect(&path.to_c_str(), None).map(|p| UnixStream { obj: p })
|
||||||
})
|
}).map_err(IoError::from_rtio_error)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Connect to a pipe named by `path`, timing out if the specified number of
|
/// Connect to a pipe named by `path`, timing out if the specified number of
|
||||||
|
@ -72,7 +72,7 @@ impl UnixStream {
|
||||||
LocalIo::maybe_raise(|io| {
|
LocalIo::maybe_raise(|io| {
|
||||||
let s = io.unix_connect(&path.to_c_str(), Some(timeout_ms));
|
let s = io.unix_connect(&path.to_c_str(), Some(timeout_ms));
|
||||||
s.map(|p| UnixStream { obj: p })
|
s.map(|p| UnixStream { obj: p })
|
||||||
})
|
}).map_err(IoError::from_rtio_error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -83,7 +83,9 @@ impl UnixStream {
|
||||||
///
|
///
|
||||||
/// Note that this method affects all cloned handles associated with this
|
/// Note that this method affects all cloned handles associated with this
|
||||||
/// stream, not just this one handle.
|
/// stream, not just this one handle.
|
||||||
pub fn close_read(&mut self) -> IoResult<()> { self.obj.close_read() }
|
pub fn close_read(&mut self) -> IoResult<()> {
|
||||||
|
self.obj.close_read().map_err(IoError::from_rtio_error)
|
||||||
|
}
|
||||||
|
|
||||||
/// Closes the writing half of this connection.
|
/// Closes the writing half of this connection.
|
||||||
///
|
///
|
||||||
|
@ -92,7 +94,9 @@ impl UnixStream {
|
||||||
///
|
///
|
||||||
/// Note that this method affects all cloned handles associated with this
|
/// Note that this method affects all cloned handles associated with this
|
||||||
/// stream, not just this one handle.
|
/// stream, not just this one handle.
|
||||||
pub fn close_write(&mut self) -> IoResult<()> { self.obj.close_write() }
|
pub fn close_write(&mut self) -> IoResult<()> {
|
||||||
|
self.obj.close_write().map_err(IoError::from_rtio_error)
|
||||||
|
}
|
||||||
|
|
||||||
/// Sets the read/write timeout for this socket.
|
/// Sets the read/write timeout for this socket.
|
||||||
///
|
///
|
||||||
|
@ -126,11 +130,15 @@ impl Clone for UnixStream {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Reader for UnixStream {
|
impl Reader for UnixStream {
|
||||||
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> { self.obj.read(buf) }
|
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
|
||||||
|
self.obj.read(buf).map_err(IoError::from_rtio_error)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Writer for UnixStream {
|
impl Writer for UnixStream {
|
||||||
fn write(&mut self, buf: &[u8]) -> IoResult<()> { self.obj.write(buf) }
|
fn write(&mut self, buf: &[u8]) -> IoResult<()> {
|
||||||
|
self.obj.write(buf).map_err(IoError::from_rtio_error)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A value that can listen for incoming named pipe connection requests.
|
/// A value that can listen for incoming named pipe connection requests.
|
||||||
|
@ -165,13 +173,15 @@ impl UnixListener {
|
||||||
pub fn bind<P: ToCStr>(path: &P) -> IoResult<UnixListener> {
|
pub fn bind<P: ToCStr>(path: &P) -> IoResult<UnixListener> {
|
||||||
LocalIo::maybe_raise(|io| {
|
LocalIo::maybe_raise(|io| {
|
||||||
io.unix_bind(&path.to_c_str()).map(|s| UnixListener { obj: s })
|
io.unix_bind(&path.to_c_str()).map(|s| UnixListener { obj: s })
|
||||||
})
|
}).map_err(IoError::from_rtio_error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Listener<UnixStream, UnixAcceptor> for UnixListener {
|
impl Listener<UnixStream, UnixAcceptor> for UnixListener {
|
||||||
fn listen(self) -> IoResult<UnixAcceptor> {
|
fn listen(self) -> IoResult<UnixAcceptor> {
|
||||||
self.obj.listen().map(|obj| UnixAcceptor { obj: obj })
|
self.obj.listen().map(|obj| {
|
||||||
|
UnixAcceptor { obj: obj }
|
||||||
|
}).map_err(IoError::from_rtio_error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,7 +212,9 @@ impl UnixAcceptor {
|
||||||
|
|
||||||
impl Acceptor<UnixStream> for UnixAcceptor {
|
impl Acceptor<UnixStream> for UnixAcceptor {
|
||||||
fn accept(&mut self) -> IoResult<UnixStream> {
|
fn accept(&mut self) -> IoResult<UnixStream> {
|
||||||
self.obj.accept().map(|s| UnixStream { obj: s })
|
self.obj.accept().map(|s| {
|
||||||
|
UnixStream { obj: s }
|
||||||
|
}).map_err(IoError::from_rtio_error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
#![allow(missing_doc)]
|
#![allow(missing_doc)]
|
||||||
|
|
||||||
use prelude::*;
|
use prelude::*;
|
||||||
use io::IoResult;
|
use io::{IoResult, IoError};
|
||||||
use libc;
|
use libc;
|
||||||
use owned::Box;
|
use owned::Box;
|
||||||
use rt::rtio::{RtioPipe, LocalIo};
|
use rt::rtio::{RtioPipe, LocalIo};
|
||||||
|
@ -51,7 +51,7 @@ impl PipeStream {
|
||||||
pub fn open(fd: libc::c_int) -> IoResult<PipeStream> {
|
pub fn open(fd: libc::c_int) -> IoResult<PipeStream> {
|
||||||
LocalIo::maybe_raise(|io| {
|
LocalIo::maybe_raise(|io| {
|
||||||
io.pipe_open(fd).map(|obj| PipeStream { obj: obj })
|
io.pipe_open(fd).map(|obj| PipeStream { obj: obj })
|
||||||
})
|
}).map_err(IoError::from_rtio_error)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
|
@ -67,11 +67,15 @@ impl Clone for PipeStream {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Reader for PipeStream {
|
impl Reader for PipeStream {
|
||||||
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> { self.obj.read(buf) }
|
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
|
||||||
|
self.obj.read(buf).map_err(IoError::from_rtio_error)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Writer for PipeStream {
|
impl Writer for PipeStream {
|
||||||
fn write(&mut self, buf: &[u8]) -> IoResult<()> { self.obj.write(buf) }
|
fn write(&mut self, buf: &[u8]) -> IoResult<()> {
|
||||||
|
self.obj.write(buf).map_err(IoError::from_rtio_error)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -16,12 +16,13 @@ use prelude::*;
|
||||||
|
|
||||||
use str;
|
use str;
|
||||||
use fmt;
|
use fmt;
|
||||||
use io::IoResult;
|
use io::{IoResult, IoError};
|
||||||
use io;
|
use io;
|
||||||
use libc;
|
use libc;
|
||||||
use mem;
|
use mem;
|
||||||
use owned::Box;
|
use owned::Box;
|
||||||
use rt::rtio::{RtioProcess, ProcessConfig, IoFactory, LocalIo};
|
use rt::rtio::{RtioProcess, ProcessConfig, IoFactory, LocalIo};
|
||||||
|
use rt::rtio;
|
||||||
use c_str::CString;
|
use c_str::CString;
|
||||||
|
|
||||||
/// Signal a process to exit, without forcibly killing it. Corresponds to
|
/// Signal a process to exit, without forcibly killing it. Corresponds to
|
||||||
|
@ -232,16 +233,25 @@ impl Command {
|
||||||
|
|
||||||
/// Executes the command as a child process, which is returned.
|
/// Executes the command as a child process, which is returned.
|
||||||
pub fn spawn(&self) -> IoResult<Process> {
|
pub fn spawn(&self) -> IoResult<Process> {
|
||||||
|
fn to_rtio(p: StdioContainer) -> rtio::StdioContainer {
|
||||||
|
match p {
|
||||||
|
Ignored => rtio::Ignored,
|
||||||
|
InheritFd(fd) => rtio::InheritFd(fd),
|
||||||
|
CreatePipe(a, b) => rtio::CreatePipe(a, b),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let extra_io: Vec<rtio::StdioContainer> =
|
||||||
|
self.extra_io.iter().map(|x| to_rtio(*x)).collect();
|
||||||
LocalIo::maybe_raise(|io| {
|
LocalIo::maybe_raise(|io| {
|
||||||
let cfg = ProcessConfig {
|
let cfg = ProcessConfig {
|
||||||
program: &self.program,
|
program: &self.program,
|
||||||
args: self.args.as_slice(),
|
args: self.args.as_slice(),
|
||||||
env: self.env.as_ref().map(|env| env.as_slice()),
|
env: self.env.as_ref().map(|env| env.as_slice()),
|
||||||
cwd: self.cwd.as_ref(),
|
cwd: self.cwd.as_ref(),
|
||||||
stdin: self.stdin,
|
stdin: to_rtio(self.stdin),
|
||||||
stdout: self.stdout,
|
stdout: to_rtio(self.stdout),
|
||||||
stderr: self.stderr,
|
stderr: to_rtio(self.stderr),
|
||||||
extra_io: self.extra_io.as_slice(),
|
extra_io: extra_io.as_slice(),
|
||||||
uid: self.uid,
|
uid: self.uid,
|
||||||
gid: self.gid,
|
gid: self.gid,
|
||||||
detach: self.detach,
|
detach: self.detach,
|
||||||
|
@ -258,7 +268,7 @@ impl Command {
|
||||||
extra_io: io.collect(),
|
extra_io: io.collect(),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
}).map_err(IoError::from_rtio_error)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Executes the command as a child process, waiting for it to finish and
|
/// Executes the command as a child process, waiting for it to finish and
|
||||||
|
@ -393,7 +403,9 @@ impl Process {
|
||||||
/// be successfully delivered if the child has exited, but not yet been
|
/// be successfully delivered if the child has exited, but not yet been
|
||||||
/// reaped.
|
/// reaped.
|
||||||
pub fn kill(id: libc::pid_t, signal: int) -> IoResult<()> {
|
pub fn kill(id: libc::pid_t, signal: int) -> IoResult<()> {
|
||||||
LocalIo::maybe_raise(|io| io.kill(id, signal))
|
LocalIo::maybe_raise(|io| {
|
||||||
|
io.kill(id, signal)
|
||||||
|
}).map_err(IoError::from_rtio_error)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the process id of this child process
|
/// Returns the process id of this child process
|
||||||
|
@ -415,7 +427,7 @@ impl Process {
|
||||||
///
|
///
|
||||||
/// If the signal delivery fails, the corresponding error is returned.
|
/// If the signal delivery fails, the corresponding error is returned.
|
||||||
pub fn signal(&mut self, signal: int) -> IoResult<()> {
|
pub fn signal(&mut self, signal: int) -> IoResult<()> {
|
||||||
self.handle.kill(signal)
|
self.handle.kill(signal).map_err(IoError::from_rtio_error)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sends a signal to this child requesting that it exits. This is
|
/// Sends a signal to this child requesting that it exits. This is
|
||||||
|
@ -442,7 +454,11 @@ impl Process {
|
||||||
/// `set_timeout` and the timeout expires before the child exits.
|
/// `set_timeout` and the timeout expires before the child exits.
|
||||||
pub fn wait(&mut self) -> IoResult<ProcessExit> {
|
pub fn wait(&mut self) -> IoResult<ProcessExit> {
|
||||||
drop(self.stdin.take());
|
drop(self.stdin.take());
|
||||||
self.handle.wait()
|
match self.handle.wait() {
|
||||||
|
Ok(rtio::ExitSignal(s)) => Ok(ExitSignal(s)),
|
||||||
|
Ok(rtio::ExitStatus(s)) => Ok(ExitStatus(s)),
|
||||||
|
Err(e) => Err(IoError::from_rtio_error(e)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets a timeout, in milliseconds, for future calls to wait().
|
/// Sets a timeout, in milliseconds, for future calls to wait().
|
||||||
|
|
|
@ -28,7 +28,7 @@ use mem::drop;
|
||||||
use option::{Some, None};
|
use option::{Some, None};
|
||||||
use owned::Box;
|
use owned::Box;
|
||||||
use result::{Ok, Err};
|
use result::{Ok, Err};
|
||||||
use rt::rtio::{IoFactory, LocalIo, RtioSignal};
|
use rt::rtio::{IoFactory, LocalIo, RtioSignal, Callback};
|
||||||
use slice::ImmutableVector;
|
use slice::ImmutableVector;
|
||||||
use vec::Vec;
|
use vec::Vec;
|
||||||
|
|
||||||
|
@ -122,17 +122,28 @@ impl Listener {
|
||||||
/// If this function fails to register a signal handler, then an error will
|
/// If this function fails to register a signal handler, then an error will
|
||||||
/// be returned.
|
/// be returned.
|
||||||
pub fn register(&mut self, signum: Signum) -> io::IoResult<()> {
|
pub fn register(&mut self, signum: Signum) -> io::IoResult<()> {
|
||||||
|
struct SignalCallback {
|
||||||
|
signum: Signum,
|
||||||
|
tx: Sender<Signum>,
|
||||||
|
}
|
||||||
|
impl Callback for SignalCallback {
|
||||||
|
fn call(&mut self) { self.tx.send(self.signum) }
|
||||||
|
}
|
||||||
|
|
||||||
if self.handles.iter().any(|&(sig, _)| sig == signum) {
|
if self.handles.iter().any(|&(sig, _)| sig == signum) {
|
||||||
return Ok(()); // self is already listening to signum, so succeed
|
return Ok(()); // self is already listening to signum, so succeed
|
||||||
}
|
}
|
||||||
match LocalIo::maybe_raise(|io| {
|
match LocalIo::maybe_raise(|io| {
|
||||||
io.signal(signum, self.tx.clone())
|
io.signal(signum as int, box SignalCallback {
|
||||||
|
signum: signum,
|
||||||
|
tx: self.tx.clone(),
|
||||||
|
})
|
||||||
}) {
|
}) {
|
||||||
Ok(handle) => {
|
Ok(handle) => {
|
||||||
self.handles.push((signum, handle));
|
self.handles.push((signum, handle));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Err(e) => Err(e)
|
Err(e) => Err(io::IoError::from_rtio_error(e))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,20 +27,19 @@ out.write(bytes!("Hello, world!"));
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use failure::local_stderr;
|
||||||
use fmt;
|
use fmt;
|
||||||
use io::{Reader, Writer, IoResult, IoError, OtherIoError,
|
use io::{Reader, Writer, IoResult, IoError, OtherIoError,
|
||||||
standard_error, EndOfFile, LineBufferedWriter, BufferedReader};
|
standard_error, EndOfFile, LineBufferedWriter, BufferedReader};
|
||||||
use libc;
|
|
||||||
use kinds::Send;
|
use kinds::Send;
|
||||||
use mem::replace;
|
use libc;
|
||||||
use option::{Option, Some, None};
|
use option::{Option, Some, None};
|
||||||
use owned::Box;
|
use owned::Box;
|
||||||
use prelude::drop;
|
|
||||||
use result::{Ok, Err};
|
use result::{Ok, Err};
|
||||||
use rt;
|
use rt;
|
||||||
use rt::local::Local;
|
use rt::local::Local;
|
||||||
use rt::rtio::{DontClose, IoFactory, LocalIo, RtioFileStream, RtioTTY};
|
|
||||||
use rt::task::Task;
|
use rt::task::Task;
|
||||||
|
use rt::rtio::{DontClose, IoFactory, LocalIo, RtioFileStream, RtioTTY};
|
||||||
use str::StrSlice;
|
use str::StrSlice;
|
||||||
|
|
||||||
// And so begins the tale of acquiring a uv handle to a stdio stream on all
|
// And so begins the tale of acquiring a uv handle to a stdio stream on all
|
||||||
|
@ -82,9 +81,11 @@ fn src<T>(fd: libc::c_int, readable: bool, f: |StdSource| -> T) -> T {
|
||||||
Ok(tty) => f(TTY(tty)),
|
Ok(tty) => f(TTY(tty)),
|
||||||
Err(_) => f(File(io.fs_from_raw_fd(fd, DontClose))),
|
Err(_) => f(File(io.fs_from_raw_fd(fd, DontClose))),
|
||||||
})
|
})
|
||||||
}).unwrap()
|
}).map_err(IoError::from_rtio_error).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
local_data_key!(local_stdout: Box<Writer:Send>)
|
||||||
|
|
||||||
/// Creates a new non-blocking handle to the stdin of the current process.
|
/// Creates a new non-blocking handle to the stdin of the current process.
|
||||||
///
|
///
|
||||||
/// The returned handled is buffered by default with a `BufferedReader`. If
|
/// The returned handled is buffered by default with a `BufferedReader`. If
|
||||||
|
@ -154,22 +155,6 @@ pub fn stderr_raw() -> StdWriter {
|
||||||
src(libc::STDERR_FILENO, false, |src| StdWriter { inner: src })
|
src(libc::STDERR_FILENO, false, |src| StdWriter { inner: src })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reset_helper(w: Box<Writer:Send>,
|
|
||||||
f: |&mut Task, Box<Writer:Send>| -> Option<Box<Writer:Send>>)
|
|
||||||
-> Option<Box<Writer:Send>> {
|
|
||||||
let mut t = Local::borrow(None::<Task>);
|
|
||||||
// Be sure to flush any pending output from the writer
|
|
||||||
match f(&mut *t, w) {
|
|
||||||
Some(mut w) => {
|
|
||||||
drop(t);
|
|
||||||
// FIXME: is failing right here?
|
|
||||||
w.flush().unwrap();
|
|
||||||
Some(w)
|
|
||||||
}
|
|
||||||
None => None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Resets the task-local stdout handle to the specified writer
|
/// Resets the task-local stdout handle to the specified writer
|
||||||
///
|
///
|
||||||
/// This will replace the current task's stdout handle, returning the old
|
/// This will replace the current task's stdout handle, returning the old
|
||||||
|
@ -179,7 +164,10 @@ fn reset_helper(w: Box<Writer:Send>,
|
||||||
/// Note that this does not need to be called for all new tasks; the default
|
/// Note that this does not need to be called for all new tasks; the default
|
||||||
/// output handle is to the process's stdout stream.
|
/// output handle is to the process's stdout stream.
|
||||||
pub fn set_stdout(stdout: Box<Writer:Send>) -> Option<Box<Writer:Send>> {
|
pub fn set_stdout(stdout: Box<Writer:Send>) -> Option<Box<Writer:Send>> {
|
||||||
reset_helper(stdout, |t, w| replace(&mut t.stdout, Some(w)))
|
local_stdout.replace(Some(stdout)).and_then(|mut s| {
|
||||||
|
let _ = s.flush();
|
||||||
|
Some(s)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resets the task-local stderr handle to the specified writer
|
/// Resets the task-local stderr handle to the specified writer
|
||||||
|
@ -191,7 +179,10 @@ pub fn set_stdout(stdout: Box<Writer:Send>) -> Option<Box<Writer:Send>> {
|
||||||
/// Note that this does not need to be called for all new tasks; the default
|
/// Note that this does not need to be called for all new tasks; the default
|
||||||
/// output handle is to the process's stderr stream.
|
/// output handle is to the process's stderr stream.
|
||||||
pub fn set_stderr(stderr: Box<Writer:Send>) -> Option<Box<Writer:Send>> {
|
pub fn set_stderr(stderr: Box<Writer:Send>) -> Option<Box<Writer:Send>> {
|
||||||
reset_helper(stderr, |t, w| replace(&mut t.stderr, Some(w)))
|
local_stderr.replace(Some(stderr)).and_then(|mut s| {
|
||||||
|
let _ = s.flush();
|
||||||
|
Some(s)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper to access the local task's stdout handle
|
// Helper to access the local task's stdout handle
|
||||||
|
@ -204,42 +195,18 @@ pub fn set_stderr(stderr: Box<Writer:Send>) -> Option<Box<Writer:Send>> {
|
||||||
// // io1 aliases io2
|
// // io1 aliases io2
|
||||||
// })
|
// })
|
||||||
// })
|
// })
|
||||||
fn with_task_stdout(f: |&mut Writer| -> IoResult<()> ) {
|
fn with_task_stdout(f: |&mut Writer| -> IoResult<()>) {
|
||||||
let task: Option<Box<Task>> = Local::try_take();
|
let result = if Local::exists(None::<Task>) {
|
||||||
let result = match task {
|
let mut my_stdout = local_stdout.replace(None).unwrap_or_else(|| {
|
||||||
Some(mut task) => {
|
box stdout() as Box<Writer:Send>
|
||||||
// Printing may run arbitrary code, so ensure that the task is in
|
});
|
||||||
// TLS to allow all std services. Note that this means a print while
|
let result = f(my_stdout);
|
||||||
// printing won't use the task's normal stdout handle, but this is
|
local_stdout.replace(Some(my_stdout));
|
||||||
// necessary to ensure safety (no aliasing).
|
result
|
||||||
let mut my_stdout = task.stdout.take();
|
} else {
|
||||||
Local::put(task);
|
|
||||||
|
|
||||||
if my_stdout.is_none() {
|
|
||||||
my_stdout = Some(box stdout() as Box<Writer:Send>);
|
|
||||||
}
|
|
||||||
let ret = f(*my_stdout.get_mut_ref());
|
|
||||||
|
|
||||||
// Note that we need to be careful when putting the stdout handle
|
|
||||||
// back into the task. If the handle was set to `Some` while
|
|
||||||
// printing, then we can run aribitrary code when destroying the
|
|
||||||
// previous handle. This means that the local task needs to be in
|
|
||||||
// TLS while we do this.
|
|
||||||
//
|
|
||||||
// To protect against this, we do a little dance in which we
|
|
||||||
// temporarily take the task, swap the handles, put the task in TLS,
|
|
||||||
// and only then drop the previous handle.
|
|
||||||
let prev = replace(&mut Local::borrow(None::<Task>).stdout, my_stdout);
|
|
||||||
drop(prev);
|
|
||||||
ret
|
|
||||||
}
|
|
||||||
|
|
||||||
None => {
|
|
||||||
let mut io = rt::Stdout;
|
let mut io = rt::Stdout;
|
||||||
f(&mut io as &mut Writer)
|
f(&mut io as &mut Writer)
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
Ok(()) => {}
|
Ok(()) => {}
|
||||||
Err(e) => fail!("failed printing to stdout: {}", e),
|
Err(e) => fail!("failed printing to stdout: {}", e),
|
||||||
|
@ -311,7 +278,7 @@ impl Reader for StdReader {
|
||||||
tty.read(buf)
|
tty.read(buf)
|
||||||
},
|
},
|
||||||
File(ref mut file) => file.read(buf).map(|i| i as uint),
|
File(ref mut file) => file.read(buf).map(|i| i as uint),
|
||||||
};
|
}.map_err(IoError::from_rtio_error);
|
||||||
match ret {
|
match ret {
|
||||||
// When reading a piped stdin, libuv will return 0-length reads when
|
// When reading a piped stdin, libuv will return 0-length reads when
|
||||||
// stdin reaches EOF. For pretty much all other streams it will
|
// stdin reaches EOF. For pretty much all other streams it will
|
||||||
|
@ -342,7 +309,9 @@ impl StdWriter {
|
||||||
/// connected to a TTY instance, or if querying the TTY instance fails.
|
/// connected to a TTY instance, or if querying the TTY instance fails.
|
||||||
pub fn winsize(&mut self) -> IoResult<(int, int)> {
|
pub fn winsize(&mut self) -> IoResult<(int, int)> {
|
||||||
match self.inner {
|
match self.inner {
|
||||||
TTY(ref mut tty) => tty.get_winsize(),
|
TTY(ref mut tty) => {
|
||||||
|
tty.get_winsize().map_err(IoError::from_rtio_error)
|
||||||
|
}
|
||||||
File(..) => {
|
File(..) => {
|
||||||
Err(IoError {
|
Err(IoError {
|
||||||
kind: OtherIoError,
|
kind: OtherIoError,
|
||||||
|
@ -362,7 +331,9 @@ impl StdWriter {
|
||||||
/// connected to a TTY instance, or if querying the TTY instance fails.
|
/// connected to a TTY instance, or if querying the TTY instance fails.
|
||||||
pub fn set_raw(&mut self, raw: bool) -> IoResult<()> {
|
pub fn set_raw(&mut self, raw: bool) -> IoResult<()> {
|
||||||
match self.inner {
|
match self.inner {
|
||||||
TTY(ref mut tty) => tty.set_raw(raw),
|
TTY(ref mut tty) => {
|
||||||
|
tty.set_raw(raw).map_err(IoError::from_rtio_error)
|
||||||
|
}
|
||||||
File(..) => {
|
File(..) => {
|
||||||
Err(IoError {
|
Err(IoError {
|
||||||
kind: OtherIoError,
|
kind: OtherIoError,
|
||||||
|
@ -387,7 +358,7 @@ impl Writer for StdWriter {
|
||||||
match self.inner {
|
match self.inner {
|
||||||
TTY(ref mut tty) => tty.write(buf),
|
TTY(ref mut tty) => tty.write(buf),
|
||||||
File(ref mut file) => file.write(buf),
|
File(ref mut file) => file.write(buf),
|
||||||
}
|
}.map_err(IoError::from_rtio_error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -413,12 +384,13 @@ mod tests {
|
||||||
})
|
})
|
||||||
|
|
||||||
iotest!(fn capture_stderr() {
|
iotest!(fn capture_stderr() {
|
||||||
use io::{ChanReader, ChanWriter};
|
use realstd::comm::channel;
|
||||||
|
use realstd::io::{Writer, ChanReader, ChanWriter, Reader};
|
||||||
|
|
||||||
let (tx, rx) = channel();
|
let (tx, rx) = channel();
|
||||||
let (mut r, w) = (ChanReader::new(rx), ChanWriter::new(tx));
|
let (mut r, w) = (ChanReader::new(rx), ChanWriter::new(tx));
|
||||||
spawn(proc() {
|
spawn(proc() {
|
||||||
set_stderr(box w);
|
::realstd::io::stdio::set_stderr(box w);
|
||||||
fail!("my special message");
|
fail!("my special message");
|
||||||
});
|
});
|
||||||
let s = r.read_to_str().unwrap();
|
let s = r.read_to_str().unwrap();
|
||||||
|
|
|
@ -17,11 +17,11 @@ and create receivers which will receive notifications after a period of time.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use comm::Receiver;
|
use comm::{Receiver, Sender, channel};
|
||||||
use io::IoResult;
|
use io::{IoResult, IoError};
|
||||||
use kinds::Send;
|
use kinds::Send;
|
||||||
use owned::Box;
|
use owned::Box;
|
||||||
use rt::rtio::{IoFactory, LocalIo, RtioTimer};
|
use rt::rtio::{IoFactory, LocalIo, RtioTimer, Callback};
|
||||||
|
|
||||||
/// A synchronous timer object
|
/// A synchronous timer object
|
||||||
///
|
///
|
||||||
|
@ -67,6 +67,8 @@ pub struct Timer {
|
||||||
obj: Box<RtioTimer:Send>,
|
obj: Box<RtioTimer:Send>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct TimerCallback { tx: Sender<()> }
|
||||||
|
|
||||||
/// Sleep the current task for `msecs` milliseconds.
|
/// Sleep the current task for `msecs` milliseconds.
|
||||||
pub fn sleep(msecs: u64) {
|
pub fn sleep(msecs: u64) {
|
||||||
let timer = Timer::new();
|
let timer = Timer::new();
|
||||||
|
@ -80,7 +82,9 @@ impl Timer {
|
||||||
/// for a number of milliseconds, or to possibly create channels which will
|
/// for a number of milliseconds, or to possibly create channels which will
|
||||||
/// get notified after an amount of time has passed.
|
/// get notified after an amount of time has passed.
|
||||||
pub fn new() -> IoResult<Timer> {
|
pub fn new() -> IoResult<Timer> {
|
||||||
LocalIo::maybe_raise(|io| io.timer_init().map(|t| Timer { obj: t }))
|
LocalIo::maybe_raise(|io| {
|
||||||
|
io.timer_init().map(|t| Timer { obj: t })
|
||||||
|
}).map_err(IoError::from_rtio_error)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Blocks the current task for `msecs` milliseconds.
|
/// Blocks the current task for `msecs` milliseconds.
|
||||||
|
@ -99,7 +103,9 @@ impl Timer {
|
||||||
/// by this timer, and that the returned receiver will be invalidated once
|
/// by this timer, and that the returned receiver will be invalidated once
|
||||||
/// the timer is destroyed (when it falls out of scope).
|
/// the timer is destroyed (when it falls out of scope).
|
||||||
pub fn oneshot(&mut self, msecs: u64) -> Receiver<()> {
|
pub fn oneshot(&mut self, msecs: u64) -> Receiver<()> {
|
||||||
self.obj.oneshot(msecs)
|
let (tx, rx) = channel();
|
||||||
|
self.obj.oneshot(msecs, box TimerCallback { tx: tx });
|
||||||
|
return rx
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a receiver which will have a continuous stream of notifications
|
/// Creates a receiver which will have a continuous stream of notifications
|
||||||
|
@ -112,7 +118,15 @@ impl Timer {
|
||||||
/// by this timer, and that the returned receiver will be invalidated once
|
/// by this timer, and that the returned receiver will be invalidated once
|
||||||
/// the timer is destroyed (when it falls out of scope).
|
/// the timer is destroyed (when it falls out of scope).
|
||||||
pub fn periodic(&mut self, msecs: u64) -> Receiver<()> {
|
pub fn periodic(&mut self, msecs: u64) -> Receiver<()> {
|
||||||
self.obj.period(msecs)
|
let (tx, rx) = channel();
|
||||||
|
self.obj.period(msecs, box TimerCallback { tx: tx });
|
||||||
|
return rx
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Callback for TimerCallback {
|
||||||
|
fn call(&mut self) {
|
||||||
|
let _ = self.tx.send_opt(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -103,8 +103,8 @@
|
||||||
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
|
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
|
||||||
html_root_url = "http://doc.rust-lang.org/",
|
html_root_url = "http://doc.rust-lang.org/",
|
||||||
html_playground_url = "http://play.rust-lang.org/")]
|
html_playground_url = "http://play.rust-lang.org/")]
|
||||||
#![feature(macro_rules, globs, asm, managed_boxes, thread_local, link_args,
|
#![feature(macro_rules, globs, managed_boxes,
|
||||||
linkage, default_type_params, phase, concat_idents, quad_precision_float)]
|
linkage, default_type_params, phase)]
|
||||||
|
|
||||||
// Don't link to std. We are std.
|
// Don't link to std. We are std.
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
@ -123,9 +123,10 @@
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
extern crate core;
|
extern crate core;
|
||||||
extern crate libc;
|
|
||||||
extern crate core_rand = "rand";
|
|
||||||
extern crate core_collections = "collections";
|
extern crate core_collections = "collections";
|
||||||
|
extern crate core_rand = "rand";
|
||||||
|
extern crate libc;
|
||||||
|
extern crate rustrt;
|
||||||
|
|
||||||
// Make std testable by not duplicating lang items. See #2912
|
// Make std testable by not duplicating lang items. See #2912
|
||||||
#[cfg(test)] extern crate realstd = "std";
|
#[cfg(test)] extern crate realstd = "std";
|
||||||
|
@ -168,6 +169,9 @@ pub use core_collections::str;
|
||||||
pub use core_collections::string;
|
pub use core_collections::string;
|
||||||
pub use core_collections::vec;
|
pub use core_collections::vec;
|
||||||
|
|
||||||
|
pub use rustrt::c_str;
|
||||||
|
pub use rustrt::local_data;
|
||||||
|
|
||||||
// Run tests with libgreen instead of libnative.
|
// Run tests with libgreen instead of libnative.
|
||||||
//
|
//
|
||||||
// FIXME: This egregiously hacks around starting the test runner in a different
|
// FIXME: This egregiously hacks around starting the test runner in a different
|
||||||
|
@ -231,19 +235,16 @@ pub mod collections;
|
||||||
|
|
||||||
pub mod task;
|
pub mod task;
|
||||||
pub mod comm;
|
pub mod comm;
|
||||||
pub mod local_data;
|
|
||||||
pub mod sync;
|
pub mod sync;
|
||||||
|
|
||||||
|
|
||||||
/* Runtime and platform support */
|
/* Runtime and platform support */
|
||||||
|
|
||||||
pub mod c_str;
|
|
||||||
pub mod c_vec;
|
pub mod c_vec;
|
||||||
pub mod os;
|
pub mod os;
|
||||||
pub mod io;
|
pub mod io;
|
||||||
pub mod path;
|
pub mod path;
|
||||||
pub mod fmt;
|
pub mod fmt;
|
||||||
pub mod cleanup;
|
|
||||||
|
|
||||||
// Private APIs
|
// Private APIs
|
||||||
#[unstable]
|
#[unstable]
|
||||||
|
@ -253,6 +254,7 @@ pub mod unstable;
|
||||||
// but name resolution doesn't work without it being pub.
|
// but name resolution doesn't work without it being pub.
|
||||||
#[unstable]
|
#[unstable]
|
||||||
pub mod rt;
|
pub mod rt;
|
||||||
|
mod failure;
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub fn issue_14344_workaround() { // FIXME #14344 force linkage to happen correctly
|
pub fn issue_14344_workaround() { // FIXME #14344 force linkage to happen correctly
|
||||||
|
|
|
@ -189,7 +189,7 @@ Accessing environment variables is not generally threadsafe.
|
||||||
Serialize access through a global lock.
|
Serialize access through a global lock.
|
||||||
*/
|
*/
|
||||||
fn with_env_lock<T>(f: || -> T) -> T {
|
fn with_env_lock<T>(f: || -> T) -> T {
|
||||||
use unstable::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT};
|
use rt::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT};
|
||||||
|
|
||||||
static mut lock: StaticNativeMutex = NATIVE_MUTEX_INIT;
|
static mut lock: StaticNativeMutex = NATIVE_MUTEX_INIT;
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
//! necessary for running libstd.
|
//! necessary for running libstd.
|
||||||
|
|
||||||
// All platforms need to link to rustrt
|
// All platforms need to link to rustrt
|
||||||
#[link(name = "rustrt", kind = "static")]
|
#[link(name = "rust_builtin", kind = "static")]
|
||||||
extern {}
|
extern {}
|
||||||
|
|
||||||
// LLVM implements the `frem` instruction as a call to `fmod`, which lives in
|
// LLVM implements the `frem` instruction as a call to `fmod`, which lives in
|
||||||
|
|
|
@ -63,7 +63,7 @@ use ptr;
|
||||||
use rt::heap::{allocate, deallocate};
|
use rt::heap::{allocate, deallocate};
|
||||||
use slice::ImmutableVector;
|
use slice::ImmutableVector;
|
||||||
use sync::atomics::{AtomicInt, AtomicPtr, SeqCst};
|
use sync::atomics::{AtomicInt, AtomicPtr, SeqCst};
|
||||||
use unstable::sync::Exclusive;
|
use rt::exclusive::Exclusive;
|
||||||
use vec::Vec;
|
use vec::Vec;
|
||||||
|
|
||||||
// Once the queue is less than 1/K full, then it will be downsized. Note that
|
// Once the queue is less than 1/K full, then it will be downsized. Note that
|
||||||
|
@ -121,7 +121,7 @@ pub enum Stolen<T> {
|
||||||
/// will only use this structure when allocating a new buffer or deallocating a
|
/// will only use this structure when allocating a new buffer or deallocating a
|
||||||
/// previous one.
|
/// previous one.
|
||||||
pub struct BufferPool<T> {
|
pub struct BufferPool<T> {
|
||||||
pool: Exclusive<Vec<Box<Buffer<T>>>>,
|
pool: Arc<Exclusive<Vec<Box<Buffer<T>>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An internal buffer used by the chase-lev deque. This structure is actually
|
/// An internal buffer used by the chase-lev deque. This structure is actually
|
||||||
|
@ -148,7 +148,7 @@ impl<T: Send> BufferPool<T> {
|
||||||
/// Allocates a new buffer pool which in turn can be used to allocate new
|
/// Allocates a new buffer pool which in turn can be used to allocate new
|
||||||
/// deques.
|
/// deques.
|
||||||
pub fn new() -> BufferPool<T> {
|
pub fn new() -> BufferPool<T> {
|
||||||
BufferPool { pool: Exclusive::new(vec!()) }
|
BufferPool { pool: Arc::new(Exclusive::new(vec!())) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Allocates a new work-stealing deque which will send/receiving memory to
|
/// Allocates a new work-stealing deque which will send/receiving memory to
|
||||||
|
@ -162,25 +162,21 @@ impl<T: Send> BufferPool<T> {
|
||||||
|
|
||||||
fn alloc(&self, bits: int) -> Box<Buffer<T>> {
|
fn alloc(&self, bits: int) -> Box<Buffer<T>> {
|
||||||
unsafe {
|
unsafe {
|
||||||
self.pool.with(|pool| {
|
let mut pool = self.pool.lock();
|
||||||
match pool.iter().position(|x| x.size() >= (1 << bits)) {
|
match pool.iter().position(|x| x.size() >= (1 << bits)) {
|
||||||
Some(i) => pool.remove(i).unwrap(),
|
Some(i) => pool.remove(i).unwrap(),
|
||||||
None => box Buffer::new(bits)
|
None => box Buffer::new(bits)
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn free(&self, buf: Box<Buffer<T>>) {
|
fn free(&self, buf: Box<Buffer<T>>) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut buf = Some(buf);
|
let mut pool = self.pool.lock();
|
||||||
self.pool.with(|pool| {
|
|
||||||
let buf = buf.take_unwrap();
|
|
||||||
match pool.iter().position(|v| v.size() > buf.size()) {
|
match pool.iter().position(|v| v.size() > buf.size()) {
|
||||||
Some(i) => pool.insert(i, buf),
|
Some(i) => pool.insert(i, buf),
|
||||||
None => pool.push(buf),
|
None => pool.push(buf),
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,12 +38,13 @@
|
||||||
|
|
||||||
use any::Any;
|
use any::Any;
|
||||||
use comm::{Sender, Receiver, channel};
|
use comm::{Sender, Receiver, channel};
|
||||||
use io::Writer;
|
use io::{Writer, stdio};
|
||||||
use kinds::{Send, marker};
|
use kinds::{Send, marker};
|
||||||
use option::{None, Some, Option};
|
use option::{None, Some, Option};
|
||||||
use owned::Box;
|
use owned::Box;
|
||||||
use result::{Result, Ok, Err};
|
use result::{Result, Ok, Err};
|
||||||
use rt::local::Local;
|
use rt::local::Local;
|
||||||
|
use rt::task;
|
||||||
use rt::task::Task;
|
use rt::task::Task;
|
||||||
use str::{Str, SendStr, IntoMaybeOwned};
|
use str::{Str, SendStr, IntoMaybeOwned};
|
||||||
|
|
||||||
|
@ -53,18 +54,10 @@ use str::{Str, SendStr, IntoMaybeOwned};
|
||||||
#[cfg(test)] use str::StrAllocating;
|
#[cfg(test)] use str::StrAllocating;
|
||||||
#[cfg(test)] use string::String;
|
#[cfg(test)] use string::String;
|
||||||
|
|
||||||
/// Indicates the manner in which a task exited.
|
|
||||||
///
|
|
||||||
/// A task that completes without failing is considered to exit successfully.
|
|
||||||
///
|
|
||||||
/// If you wish for this result's delivery to block until all
|
|
||||||
/// children tasks complete, recommend using a result future.
|
|
||||||
pub type TaskResult = Result<(), Box<Any:Send>>;
|
|
||||||
|
|
||||||
/// Task configuration options
|
/// Task configuration options
|
||||||
pub struct TaskOpts {
|
pub struct TaskOpts {
|
||||||
/// Enable lifecycle notifications on the given channel
|
/// Enable lifecycle notifications on the given channel
|
||||||
pub notify_chan: Option<Sender<TaskResult>>,
|
pub notify_chan: Option<Sender<task::Result>>,
|
||||||
/// A name for the task-to-be, for identification in failure messages
|
/// A name for the task-to-be, for identification in failure messages
|
||||||
pub name: Option<SendStr>,
|
pub name: Option<SendStr>,
|
||||||
/// The size of the stack for the spawned task
|
/// The size of the stack for the spawned task
|
||||||
|
@ -114,7 +107,7 @@ impl TaskBuilder {
|
||||||
///
|
///
|
||||||
/// # Failure
|
/// # Failure
|
||||||
/// Fails if a future_result was already set for this task.
|
/// Fails if a future_result was already set for this task.
|
||||||
pub fn future_result(&mut self) -> Receiver<TaskResult> {
|
pub fn future_result(&mut self) -> Receiver<task::Result> {
|
||||||
// FIXME (#3725): Once linked failure and notification are
|
// FIXME (#3725): Once linked failure and notification are
|
||||||
// handled in the library, I can imagine implementing this by just
|
// handled in the library, I can imagine implementing this by just
|
||||||
// registering an arbitrary number of task::on_exit handlers and
|
// registering an arbitrary number of task::on_exit handlers and
|
||||||
|
@ -180,7 +173,28 @@ impl TaskBuilder {
|
||||||
Some(t) => t,
|
Some(t) => t,
|
||||||
None => fail!("need a local task to spawn a new task"),
|
None => fail!("need a local task to spawn a new task"),
|
||||||
};
|
};
|
||||||
t.spawn_sibling(self.opts, f);
|
let TaskOpts { notify_chan, name, stack_size, stdout, stderr } = self.opts;
|
||||||
|
|
||||||
|
let opts = task::TaskOpts {
|
||||||
|
on_exit: notify_chan.map(|c| proc(r) c.send(r)),
|
||||||
|
name: name,
|
||||||
|
stack_size: stack_size,
|
||||||
|
};
|
||||||
|
if stdout.is_some() || stderr.is_some() {
|
||||||
|
t.spawn_sibling(opts, proc() {
|
||||||
|
match stdout {
|
||||||
|
Some(handle) => { let _ = stdio::set_stdout(handle); }
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
match stderr {
|
||||||
|
Some(handle) => { let _ = stdio::set_stderr(handle); }
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
t.spawn_sibling(opts, f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -224,7 +224,7 @@ pub mod dl {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_for_errors_in<T>(f: || -> T) -> Result<T, String> {
|
pub fn check_for_errors_in<T>(f: || -> T) -> Result<T, String> {
|
||||||
use unstable::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT};
|
use rt::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT};
|
||||||
static mut lock: StaticNativeMutex = NATIVE_MUTEX_INIT;
|
static mut lock: StaticNativeMutex = NATIVE_MUTEX_INIT;
|
||||||
unsafe {
|
unsafe {
|
||||||
// dlerror isn't thread safe, so we need to lock around this entire
|
// dlerror isn't thread safe, so we need to lock around this entire
|
||||||
|
|
|
@ -11,7 +11,3 @@
|
||||||
#![doc(hidden)]
|
#![doc(hidden)]
|
||||||
|
|
||||||
pub mod dynamic_lib;
|
pub mod dynamic_lib;
|
||||||
|
|
||||||
pub mod sync;
|
|
||||||
pub mod mutex;
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue