use rt::rtio::{RtioFileStream, IoFactory, LocalIo};
use io;
use option::{Some, None, Option};
-use result::{Ok, Err, Result};
+use result::{Ok, Err};
use path;
use path::{Path, GenericPath};
use vec::{OwnedVector, ImmutableVector};
priv last_nread: int,
}
-fn io_raise<T>(f: |io: &mut IoFactory| -> Result<T, IoError>) -> Option<T> {
- let mut io = LocalIo::borrow();
- match f(io.get()) {
- Ok(t) => Some(t),
- Err(ioerr) => {
- io_error::cond.raise(ioerr);
- None
- }
- }
-}
-
impl File {
/// Open a file at `path` in the mode specified by the `mode` and `access`
/// arguments
pub fn open_mode(path: &Path,
mode: FileMode,
access: FileAccess) -> Option<File> {
- let mut io = LocalIo::borrow();
- match io.get().fs_open(&path.to_c_str(), mode, access) {
- Ok(fd) => Some(File {
- path: path.clone(),
- fd: fd,
- last_nread: -1
- }),
- Err(ioerr) => {
- io_error::cond.raise(ioerr);
- None
- }
- }
+ LocalIo::maybe_raise(|io| {
+ io.fs_open(&path.to_c_str(), mode, access).map(|fd| {
+ File {
+ path: path.clone(),
+ fd: fd,
+ last_nread: -1
+ }
+ })
+ })
}
/// Attempts to open a file in read-only mode. This function is equivalent to
/// directory, the user lacks permissions to remove the file, or if some
/// other filesystem-level error occurs.
pub fn unlink(path: &Path) {
- io_raise(|io| io.fs_unlink(&path.to_c_str()));
+ LocalIo::maybe_raise(|io| io.fs_unlink(&path.to_c_str()));
}
/// Given a path, query the file system to get information about a file,
/// requisite permissions to perform a `stat` call on the given path or if
/// there is no entry in the filesystem at the provided path.
pub fn stat(path: &Path) -> FileStat {
- io_raise(|io| io.fs_stat(&path.to_c_str())).unwrap_or_else(dummystat)
+ LocalIo::maybe_raise(|io| {
+ io.fs_stat(&path.to_c_str())
+ }).unwrap_or_else(dummystat)
}
fn dummystat() -> FileStat {
///
/// See `stat`
pub fn lstat(path: &Path) -> FileStat {
- io_raise(|io| io.fs_lstat(&path.to_c_str())).unwrap_or_else(dummystat)
+ LocalIo::maybe_raise(|io| {
+ io.fs_lstat(&path.to_c_str())
+ }).unwrap_or_else(dummystat)
}
/// Rename a file or directory to a new name.
/// the process lacks permissions to view the contents, or if some other
/// intermittent I/O error occurs.
pub fn rename(from: &Path, to: &Path) {
- io_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()));
}
/// Copies the contents of one file to another. This function will also
/// condition. Some possible error situations are not having the permission to
/// change the attributes of a file or the file not existing.
pub fn chmod(path: &Path, mode: io::FilePermission) {
- io_raise(|io| io.fs_chmod(&path.to_c_str(), mode));
+ LocalIo::maybe_raise(|io| io.fs_chmod(&path.to_c_str(), mode));
}
/// Change the user and group owners of a file at the specified path.
///
/// This function will raise on the `io_error` condition on failure.
pub fn chown(path: &Path, uid: int, gid: int) {
- io_raise(|io| io.fs_chown(&path.to_c_str(), uid, gid));
+ LocalIo::maybe_raise(|io| io.fs_chown(&path.to_c_str(), uid, gid));
}
/// Creates a new hard link on the filesystem. The `dst` path will be a
///
/// This function will raise on the `io_error` condition on failure.
pub fn link(src: &Path, dst: &Path) {
- io_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()));
}
/// Creates a new symbolic link on the filesystem. The `dst` path will be a
///
/// This function will raise on the `io_error` condition on failure.
pub fn symlink(src: &Path, dst: &Path) {
- io_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()));
}
/// Reads a symlink, returning the file that the symlink points to.
/// conditions include reading a file that does not exist or reading a file
/// which is not a symlink.
pub fn readlink(path: &Path) -> Option<Path> {
- io_raise(|io| io.fs_readlink(&path.to_c_str()))
+ LocalIo::maybe_raise(|io| io.fs_readlink(&path.to_c_str()))
}
/// Create a new, empty directory at the provided path
/// to make a new directory at the provided path, or if the directory already
/// exists.
pub fn mkdir(path: &Path, mode: FilePermission) {
- io_raise(|io| io.fs_mkdir(&path.to_c_str(), mode));
+ LocalIo::maybe_raise(|io| io.fs_mkdir(&path.to_c_str(), mode));
}
/// Remove an existing, empty directory
/// to remove the directory at the provided path, or if the directory isn't
/// empty.
pub fn rmdir(path: &Path) {
- io_raise(|io| io.fs_rmdir(&path.to_c_str()));
+ LocalIo::maybe_raise(|io| io.fs_rmdir(&path.to_c_str()));
}
/// Retrieve a vector containing all entries within a provided directory
/// the process lacks permissions to view the contents or if the `path` points
/// at a non-directory file
pub fn readdir(path: &Path) -> ~[Path] {
- io_raise(|io| io.fs_readdir(&path.to_c_str(), 0)).unwrap_or_else(|| ~[])
+ LocalIo::maybe_raise(|io| {
+ io.fs_readdir(&path.to_c_str(), 0)
+ }).unwrap_or_else(|| ~[])
}
/// Returns an iterator which will recursively walk the directory structure
/// happens.
// FIXME(#10301) these arguments should not be u64
pub fn change_file_times(path: &Path, atime: u64, mtime: u64) {
- io_raise(|io| io.fs_utime(&path.to_c_str(), atime, mtime));
+ LocalIo::maybe_raise(|io| io.fs_utime(&path.to_c_str(), atime, mtime));
}
impl Reader for File {
*/
use option::{Option, Some, None};
-use result::{Ok, Err};
-use io::{io_error};
use io::net::ip::{SocketAddr, IpAddr};
use rt::rtio::{IoFactory, LocalIo};
use vec::ImmutableVector;
/// consumption just yet.
fn lookup(hostname: Option<&str>, servname: Option<&str>, hint: Option<Hint>)
-> Option<~[Info]> {
- let mut io = LocalIo::borrow();
- match io.get().get_host_addresses(hostname, servname, hint) {
- Ok(i) => Some(i),
- Err(ioerr) => {
- io_error::cond.raise(ioerr);
- None
- }
- }
+ LocalIo::maybe_raise(|io| io.get_host_addresses(hostname, servname, hint))
}
#[cfg(test)]
}
pub fn connect(addr: SocketAddr) -> Option<TcpStream> {
- let result = {
- let mut io = LocalIo::borrow();
- io.get().tcp_connect(addr)
- };
- match result {
- Ok(s) => Some(TcpStream::new(s)),
- Err(ioerr) => {
- io_error::cond.raise(ioerr);
- None
- }
- }
+ LocalIo::maybe_raise(|io| {
+ io.tcp_connect(addr).map(TcpStream::new)
+ })
}
pub fn peer_name(&mut self) -> Option<SocketAddr> {
impl TcpListener {
pub fn bind(addr: SocketAddr) -> Option<TcpListener> {
- let mut io = LocalIo::borrow();
- match io.get().tcp_bind(addr) {
- Ok(l) => Some(TcpListener { obj: l }),
- Err(ioerr) => {
- io_error::cond.raise(ioerr);
- None
- }
- }
+ LocalIo::maybe_raise(|io| {
+ io.tcp_bind(addr).map(|l| TcpListener { obj: l })
+ })
}
pub fn socket_name(&mut self) -> Option<SocketAddr> {
impl UdpSocket {
pub fn bind(addr: SocketAddr) -> Option<UdpSocket> {
- let mut io = LocalIo::borrow();
- match io.get().udp_bind(addr) {
- Ok(s) => Some(UdpSocket { obj: s }),
- Err(ioerr) => {
- io_error::cond.raise(ioerr);
- None
- }
- }
+ LocalIo::maybe_raise(|io| {
+ io.udp_bind(addr).map(|s| UdpSocket { obj: s })
+ })
}
pub fn recvfrom(&mut self, buf: &mut [u8]) -> Option<(uint, SocketAddr)> {
/// stream.write([1, 2, 3]);
///
pub fn connect<P: ToCStr>(path: &P) -> Option<UnixStream> {
- let mut io = LocalIo::borrow();
- match io.get().unix_connect(&path.to_c_str()) {
- Ok(s) => Some(UnixStream::new(s)),
- Err(ioerr) => {
- io_error::cond.raise(ioerr);
- None
- }
- }
+ LocalIo::maybe_raise(|io| {
+ io.unix_connect(&path.to_c_str()).map(UnixStream::new)
+ })
}
}
/// }
///
pub fn bind<P: ToCStr>(path: &P) -> Option<UnixListener> {
- let mut io = LocalIo::borrow();
- match io.get().unix_bind(&path.to_c_str()) {
- Ok(s) => Some(UnixListener{ obj: s }),
- Err(ioerr) => {
- io_error::cond.raise(ioerr);
- None
- }
- }
+ LocalIo::maybe_raise(|io| {
+ io.unix_bind(&path.to_c_str()).map(|s| UnixListener { obj: s })
+ })
}
}
//! enough so that pipes can be created to child processes.
use prelude::*;
-use super::{Reader, Writer};
use io::{io_error, EndOfFile};
-use io::native::file;
-use rt::rtio::{LocalIo, RtioPipe};
+use libc;
+use rt::rtio::{RtioPipe, LocalIo};
pub struct PipeStream {
priv obj: ~RtioPipe,
///
/// If the pipe cannot be created, an error will be raised on the
/// `io_error` condition.
- pub fn open(fd: file::fd_t) -> Option<PipeStream> {
- let mut io = LocalIo::borrow();
- match io.get().pipe_open(fd) {
- Ok(obj) => Some(PipeStream { obj: obj }),
- Err(e) => {
- io_error::cond.raise(e);
- None
- }
- }
+ pub fn open(fd: libc::c_int) -> Option<PipeStream> {
+ LocalIo::maybe_raise(|io| {
+ io.pipe_open(fd).map(|obj| PipeStream { obj: obj })
+ })
}
pub fn new(inner: ~RtioPipe) -> PipeStream {
/// Creates a new pipe initialized, but not bound to any particular
/// source/destination
pub fn new(config: ProcessConfig) -> Option<Process> {
- let mut io = LocalIo::borrow();
- match io.get().spawn(config) {
- Ok((p, io)) => Some(Process{
- handle: p,
- io: io.move_iter().map(|p|
- p.map(|p| io::PipeStream::new(p))
- ).collect()
- }),
- Err(ioerr) => {
- io_error::cond.raise(ioerr);
- None
- }
- }
+ let mut config = Some(config);
+ LocalIo::maybe_raise(|io| {
+ io.spawn(config.take_unwrap()).map(|(p, io)| {
+ Process {
+ handle: p,
+ io: io.move_iter().map(|p| {
+ p.map(|p| io::PipeStream::new(p))
+ }).collect()
+ }
+ })
+ })
}
/// Returns the process id of this child process
use comm::{Port, SharedChan};
use container::{Map, MutableMap};
use hashmap;
-use io::io_error;
-use result::{Err, Ok};
+use option::{Some, None};
use rt::rtio::{IoFactory, LocalIo, RtioSignal};
#[repr(int)]
if self.handles.contains_key(&signum) {
return true; // self is already listening to signum, so succeed
}
- let mut io = LocalIo::borrow();
- match io.get().signal(signum, self.chan.clone()) {
- Ok(w) => {
- self.handles.insert(signum, w);
+ match LocalIo::maybe_raise(|io| {
+ io.signal(signum, self.chan.clone())
+ }) {
+ Some(handle) => {
+ self.handles.insert(signum, handle);
true
- },
- Err(ioerr) => {
- io_error::cond.raise(ioerr);
- false
}
+ None => false
}
}
*/
use fmt;
+use io::buffered::LineBufferedWriter;
+use io::{Reader, Writer, io_error, IoError, OtherIoError,
+ standard_error, EndOfFile};
use libc;
use option::{Option, Some, None};
use result::{Ok, Err};
-use io::buffered::LineBufferedWriter;
use rt::rtio::{DontClose, IoFactory, LocalIo, RtioFileStream, RtioTTY};
-use super::{Reader, Writer, io_error, IoError, OtherIoError,
- standard_error, EndOfFile};
+use vec;
// And so begins the tale of acquiring a uv handle to a stdio stream on all
// platforms in all situations. Our story begins by splitting the world into two
}
fn src<T>(fd: libc::c_int, readable: bool, f: |StdSource| -> T) -> T {
- let mut io = LocalIo::borrow();
- match io.get().tty_open(fd, readable) {
- Ok(tty) => f(TTY(tty)),
- Err(_) => {
- // It's not really that desirable if these handles are closed
- // synchronously, and because they're squirreled away in a task
- // structure the destructors will be run when the task is
- // attempted to get destroyed. This means that if we run a
- // synchronous destructor we'll attempt to do some scheduling
- // operations which will just result in sadness.
- f(File(io.get().fs_from_raw_fd(fd, DontClose)))
- }
- }
+ LocalIo::maybe_raise(|io| {
+ Ok(match io.tty_open(fd, readable) {
+ Ok(tty) => f(TTY(tty)),
+ Err(_) => f(File(io.fs_from_raw_fd(fd, DontClose))),
+ })
+ }).unwrap()
}
/// Creates a new non-blocking handle to the stdin of the current process.
*/
use comm::Port;
-use option::{Option, Some, None};
-use result::{Ok, Err};
-use io::io_error;
+use option::Option;
use rt::rtio::{IoFactory, LocalIo, RtioTimer};
pub struct Timer {
/// for a number of milliseconds, or to possibly create channels which will
/// get notified after an amount of time has passed.
pub fn new() -> Option<Timer> {
- let mut io = LocalIo::borrow();
- match io.get().timer_init() {
- Ok(t) => Some(Timer { obj: t }),
- Err(ioerr) => {
- debug!("Timer::init: failed to init: {:?}", ioerr);
- io_error::cond.raise(ioerr);
- None
- }
- }
+ LocalIo::maybe_raise(|io| io.timer_init().map(|t| Timer { obj: t }))
}
/// Blocks the current task for `msecs` milliseconds.
impl<'a> LocalIo<'a> {
/// Returns the local I/O: either the local scheduler's I/O services or
/// the native I/O services.
- pub fn borrow() -> LocalIo {
- use rt::sched::Scheduler;
- use rt::local::Local;
+ pub fn borrow() -> Option<LocalIo> {
+ // XXX: This is currently very unsafely implemented. We don't actually
+ // *take* the local I/O so there's a very real possibility that we
+ // can have two borrows at once. Currently there is not a clear way
+ // to actually borrow the local I/O factory safely because even if
+ // ownership were transferred down to the functions that the I/O
+ // factory implements it's just too much of a pain to know when to
+ // relinquish ownership back into the local task (but that would be
+ // the safe way of implementing this function).
+ //
+ // In order to get around this, we just transmute a copy out of the task
+ // in order to have what is likely a static lifetime (bad).
+ let mut t: ~Task = Local::take();
+ let ret = t.local_io().map(|t| {
+ unsafe { cast::transmute_copy(&t) }
+ });
+ Local::put(t);
+ return ret;
+ }
- unsafe {
- // First, attempt to use the local scheduler's I/O services
- let sched: Option<*mut Scheduler> = Local::try_unsafe_borrow();
- match sched {
- Some(sched) => {
- match (*sched).event_loop.io() {
- Some(factory) => {
- return LocalIo {
- factory: factory,
- }
- }
- None => {}
+ pub fn maybe_raise<T>(f: |io: &mut IoFactory| -> Result<T, IoError>)
+ -> Option<T>
+ {
+ match LocalIo::borrow() {
+ None => {
+ io::io_error::cond.raise(io::standard_error(io::IoUnavailable));
+ None
+ }
+ Some(mut io) => {
+ match f(io.get()) {
+ Ok(t) => Some(t),
+ Err(ioerr) => {
+ io::io_error::cond.raise(ioerr);
+ None
}
}
- None => {}
- }
- // If we don't have a scheduler or the scheduler doesn't have I/O
- // services, then fall back to the native I/O services.
- let native_io: &'static mut native::IoFactory =
- &mut NATIVE_IO_FACTORY;
- LocalIo {
- factory: native_io as &mut IoFactory:'static
}
}
}
+ pub fn new<'a>(io: &'a mut IoFactory) -> LocalIo<'a> {
+ LocalIo { factory: io }
+ }
+
/// Returns the underlying I/O factory as a trait reference.
#[inline]
pub fn get<'a>(&'a mut self) -> &'a mut IoFactory {