diff --git a/src/librustpkg/installed_packages.rs b/src/librustpkg/installed_packages.rs index b1e3d1bd879..48c25a53682 100644 --- a/src/librustpkg/installed_packages.rs +++ b/src/librustpkg/installed_packages.rs @@ -19,7 +19,10 @@ use std::io::fs; pub fn list_installed_packages(f: |&PkgId| -> bool) -> bool { let workspaces = rust_path(); for p in workspaces.iter() { - let binfiles = io::ignore_io_error(|| fs::readdir(&p.join("bin"))); + let binfiles = { + let _guard = io::ignore_io_error(); + fs::readdir(&p.join("bin")) + }; for exec in binfiles.iter() { // FIXME (#9639): This needs to handle non-utf8 paths match exec.filestem_str() { @@ -31,7 +34,10 @@ pub fn list_installed_packages(f: |&PkgId| -> bool) -> bool { } } } - let libfiles = io::ignore_io_error(|| fs::readdir(&p.join("lib"))); + let libfiles = { + let _guard = io::ignore_io_error(); + fs::readdir(&p.join("lib")) + }; for lib in libfiles.iter() { debug!("Full name: {}", lib.display()); match has_library(lib) { @@ -55,7 +61,10 @@ pub fn list_installed_packages(f: |&PkgId| -> bool) -> bool { } pub fn has_library(p: &Path) -> Option<~str> { - let files = io::ignore_io_error(|| fs::readdir(p)); + let files = { + let _guard = io::ignore_io_error(); + fs::readdir(p) + }; for path in files.iter() { if path.extension_str() == Some(os::consts::DLL_EXTENSION) { let stuff : &str = path.filestem_str().expect("has_library: weird path"); diff --git a/src/librustpkg/path_util.rs b/src/librustpkg/path_util.rs index 4b5e1ce8727..7a17d362625 100644 --- a/src/librustpkg/path_util.rs +++ b/src/librustpkg/path_util.rs @@ -217,7 +217,10 @@ pub fn system_library(sysroot: &Path, lib_name: &str) -> Option { fn library_in(short_name: &str, version: &Version, dir_to_search: &Path) -> Option { debug!("Listing directory {}", dir_to_search.display()); - let dir_contents = io::ignore_io_error(|| fs::readdir(dir_to_search)); + let dir_contents = { + let _guard = io::ignore_io_error(); + fs::readdir(dir_to_search) + }; debug!("dir has {:?} entries", dir_contents.len()); let lib_prefix = format!("{}{}", os::consts::DLL_PREFIX, short_name); diff --git a/src/libstd/condition.rs b/src/libstd/condition.rs index e34e94ac10c..c5d6ce2f3df 100644 --- a/src/libstd/condition.rs +++ b/src/libstd/condition.rs @@ -162,7 +162,7 @@ impl Condition { /// /// Normally this object is not dealt with directly, but rather it's directly /// used after being returned from `trap` -struct Trap<'self, T, U> { +pub struct Trap<'self, T, U> { priv cond: &'self Condition, priv handler: @Handler } @@ -187,10 +187,24 @@ impl<'self, T, U> Trap<'self, T, U> { local_data::set(self.cond.key, self.handler); inner() } + + /// Returns a guard that will automatically reset the condition upon + /// exit of the scope. This is useful if you want to use conditions with + /// an RAII pattern. + pub fn guard(&self) -> Guard<'self,T,U> { + let guard = Guard { + cond: self.cond + }; + debug!("Guard: pushing handler to TLS"); + local_data::set(self.cond.key, self.handler); + guard + } } -#[doc(hidden)] -struct Guard<'self, T, U> { +/// A guard that will automatically reset the condition handler upon exit of +/// the scope. This is useful if you want to use conditions with an RAII +/// pattern. +pub struct Guard<'self, T, U> { priv cond: &'self Condition } diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index edc6728a0c1..d5e216e2426 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -241,6 +241,7 @@ Out of scope #[allow(missing_doc)]; use cast; +use condition::Guard; use container::Container; use int; use iter::Iterator; @@ -394,12 +395,12 @@ condition! { /// Helper for wrapper calls where you want to /// ignore any io_errors that might be raised -pub fn ignore_io_error(cb: || -> T) -> T { +pub fn ignore_io_error() -> Guard<'static,IoError,()> { io_error::cond.trap(|_| { // just swallow the error.. downstream users // who can make a decision based on a None result // won't care - }).inside(|| cb()) + }).guard() } /// Helper for catching an I/O error and wrapping it in a Result object. The diff --git a/src/libstd/os.rs b/src/libstd/os.rs index ff939310865..bcd353bab7a 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -1477,7 +1477,9 @@ mod tests { assert!(*chunk.data == 0xbe); close(fd); } - io::ignore_io_error(|| fs::unlink(&path)); + + let _guard = io::ignore_io_error(); + fs::unlink(&path); } // More recursive_mkdir tests are in extra::tempfile diff --git a/src/libstd/run.rs b/src/libstd/run.rs index 2447bba98d6..f4c6cdbd934 100644 --- a/src/libstd/run.rs +++ b/src/libstd/run.rs @@ -12,7 +12,6 @@ #[allow(missing_doc)]; -use cell::Cell; use comm::{stream, SharedChan}; use io::Reader; use io::process::ProcessExit; @@ -212,8 +211,8 @@ impl Process { */ pub fn finish_with_output(&mut self) -> ProcessOutput { self.close_input(); - let output = Cell::new(self.inner.io[1].take()); - let error = Cell::new(self.inner.io[2].take()); + let output = self.inner.io[1].take(); + let error = self.inner.io[2].take(); // Spawn two entire schedulers to read both stdout and sterr // in parallel so we don't deadlock while blocking on one @@ -224,20 +223,20 @@ impl Process { let ch_clone = ch.clone(); do spawn { - io::ignore_io_error(|| { - match error.take() { - Some(ref mut e) => ch.send((2, e.read_to_end())), - None => ch.send((2, ~[])) - } - }) + let _guard = io::ignore_io_error(); + let mut error = error; + match error { + Some(ref mut e) => ch.send((2, e.read_to_end())), + None => ch.send((2, ~[])) + } } do spawn { - io::ignore_io_error(|| { - match output.take() { - Some(ref mut e) => ch_clone.send((1, e.read_to_end())), - None => ch_clone.send((1, ~[])) - } - }) + let _guard = io::ignore_io_error(); + let mut output = output; + match output { + Some(ref mut e) => ch_clone.send((1, e.read_to_end())), + None => ch_clone.send((1, ~[])) + } } let status = self.finish(); diff --git a/src/test/bench/shootout-k-nucleotide-pipes.rs b/src/test/bench/shootout-k-nucleotide-pipes.rs index 76d2ca1f30b..ac2b1958f93 100644 --- a/src/test/bench/shootout-k-nucleotide-pipes.rs +++ b/src/test/bench/shootout-k-nucleotide-pipes.rs @@ -189,8 +189,12 @@ fn main() { let mut proc_mode = false; loop { - let line = match io::ignore_io_error(|| rdr.read_line()) { - Some(ln) => ln, None => break, + let line = { + let _guard = io::ignore_io_error(); + match rdr.read_line() { + Some(ln) => ln, + None => break, + } }; let line = line.trim().to_owned();