Skip to content

Commit

Permalink
auto merge of #10218 : alexcrichton/rust/stdio-flush-safe, r=cmr
Browse files Browse the repository at this point in the history
The previous method was unsound because you could very easily create two mutable
pointers which alias the same location (not sound behavior). This hides the
function which does so and then exports an explicit flush() function (with
documentation about how it works).
  • Loading branch information
bors committed Nov 1, 2013
2 parents a300314 + 8f258ab commit 3a15482
Showing 1 changed file with 27 additions and 14 deletions.
41 changes: 27 additions & 14 deletions src/libstd/rt/io/stdio.rs
Expand Up @@ -112,20 +112,17 @@ pub fn stderr() -> StdWriter {
do src(libc::STDERR_FILENO, false) |src| { StdWriter { inner: src } }
}

/// Executes a closure with the local task's handle on stdout. By default, this
/// stream is a buffering stream, so the handled yielded to the given closure
/// can be used to flush the stdout stream (if necessary). The buffering used is
/// line-buffering when stdout is attached to a terminal, and a fixed sized
/// buffer if it is not attached to a terminal.
///
/// Note that handles generated via the `stdout()` function all output to the
/// same stream, and output among all task may be interleaved as a result of
/// this. This is provided to have access to the default stream for `print` and
/// `println` (and the related macros) for this task.
///
/// Also note that logging macros do not use this stream. Using the logging
/// macros will emit output to stderr.
pub fn with_task_stdout(f: &fn(&mut Writer)) {
// Helper to access the local task's stdout handle
//
// Note that this is not a safe function to expose because you can create an
// aliased pointer very easily:
//
// do with_task_stdout |io1| {
// do with_task_stdout |io2| {
// // io1 aliases io2
// }
// }
fn with_task_stdout(f: &fn(&mut Writer)) {
use rt::local::Local;
use rt::task::Task;

Expand Down Expand Up @@ -153,6 +150,22 @@ pub fn with_task_stdout(f: &fn(&mut Writer)) {
}
}

/// Flushes the local task's stdout handle.
///
/// By default, this stream is a buffering stream, flushing may be necessary to
/// ensure output is on the terminal screen. The buffering used is
/// line-buffering when stdout is attached to a terminal, and a fixed sized
/// buffer if it is not attached to a terminal.
///
/// Note that logging macros do not use this stream. Using the logging macros
/// will emit output to stderr, and while they are line buffered the log
/// messages are always terminated in a newline (no need to flush).
pub fn flush() {
do with_task_stdout |io| {
io.flush();
}
}

/// Prints a string to the stdout of the current process. No newline is emitted
/// after the string is printed.
pub fn print(s: &str) {
Expand Down

0 comments on commit 3a15482

Please sign in to comment.