1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
14 use cell
::{RefCell, BorrowState}
;
18 use io
::{self, BufReader, LineWriter}
;
19 use sync
::{Arc, Mutex, MutexGuard}
;
21 use sys_common
::remutex
::{ReentrantMutex, ReentrantMutexGuard}
;
23 /// Stdout used by print! and println! macros
25 static LOCAL_STDOUT
: RefCell
<Option
<Box
<Write
+ Send
>>> = {
30 /// A handle to a raw instance of the standard input stream of this process.
32 /// This handle is not synchronized or buffered in any fashion. Constructed via
33 /// the `std::io::stdio::stdin_raw` function.
34 struct StdinRaw(stdio
::Stdin
);
36 /// A handle to a raw instance of the standard output stream of this process.
38 /// This handle is not synchronized or buffered in any fashion. Constructed via
39 /// the `std::io::stdio::stdout_raw` function.
40 struct StdoutRaw(stdio
::Stdout
);
42 /// A handle to a raw instance of the standard output stream of this process.
44 /// This handle is not synchronized or buffered in any fashion. Constructed via
45 /// the `std::io::stdio::stderr_raw` function.
46 struct StderrRaw(stdio
::Stderr
);
48 /// Constructs a new raw handle to the standard input of this process.
50 /// The returned handle does not interact with any other handles created nor
51 /// handles returned by `std::io::stdin`. Data buffered by the `std::io::stdin`
52 /// handles is **not** available to raw handles returned from this function.
54 /// The returned handle has no external synchronization or buffering.
55 fn stdin_raw() -> StdinRaw { StdinRaw(stdio::Stdin::new()) }
57 /// Constructs a new raw handle to the standard input stream of this process.
59 /// The returned handle does not interact with any other handles created nor
60 /// handles returned by `std::io::stdout`. Note that data is buffered by the
61 /// `std::io::stdin` handles so writes which happen via this raw handle may
62 /// appear before previous writes.
64 /// The returned handle has no external synchronization or buffering layered on
66 fn stdout_raw() -> StdoutRaw { StdoutRaw(stdio::Stdout::new()) }
68 /// Constructs a new raw handle to the standard input stream of this process.
70 /// The returned handle does not interact with any other handles created nor
71 /// handles returned by `std::io::stdout`.
73 /// The returned handle has no external synchronization or buffering layered on
75 fn stderr_raw() -> StderrRaw { StderrRaw(stdio::Stderr::new()) }
77 impl Read
for StdinRaw
{
78 fn read(&mut self, buf
: &mut [u8]) -> io
::Result
<usize> { self.0.read(buf) }
80 impl Write
for StdoutRaw
{
81 fn write(&mut self, buf
: &[u8]) -> io
::Result
<usize> { self.0.write(buf) }
82 fn flush(&mut self) -> io
::Result
<()> { Ok(()) }
84 impl Write
for StderrRaw
{
85 fn write(&mut self, buf
: &[u8]) -> io
::Result
<usize> { self.0.write(buf) }
86 fn flush(&mut self) -> io
::Result
<()> { Ok(()) }
89 /// A handle to the standard input stream of a process.
91 /// Each handle is a shared reference to a global buffer of input data to this
92 /// process. A handle can be `lock`'d to gain full access to `BufRead` methods
93 /// (e.g. `.lines()`). Writes to this handle are otherwise locked with respect
96 /// This handle implements the `Read` trait, but beware that concurrent reads
97 /// of `Stdin` must be executed with care.
99 /// Created by the function `io::stdin()`.
100 #[stable(feature = "rust1", since = "1.0.0")]
102 inner
: Arc
<Mutex
<BufReader
<StdinRaw
>>>,
105 /// A locked reference to the a `Stdin` handle.
107 /// This handle implements both the `Read` and `BufRead` traits and is
108 /// constructed via the `lock` method on `Stdin`.
109 #[stable(feature = "rust1", since = "1.0.0")]
110 pub struct StdinLock
<'a
> {
111 inner
: MutexGuard
<'a
, BufReader
<StdinRaw
>>,
114 /// Creates a new handle to the global standard input stream of this process.
116 /// The handle returned refers to a globally shared buffer between all threads.
117 /// Access is synchronized and can be explicitly controlled with the `lock()`
120 /// The `Read` trait is implemented for the returned value but the `BufRead`
121 /// trait is not due to the global nature of the standard input stream. The
122 /// locked version, `StdinLock`, implements both `Read` and `BufRead`, however.
123 #[stable(feature = "rust1", since = "1.0.0")]
124 pub fn stdin() -> Stdin
{
125 static INSTANCE
: Lazy
<Mutex
<BufReader
<StdinRaw
>>> = lazy_init
!(stdin_init
);
127 inner
: INSTANCE
.get().expect("cannot access stdin during shutdown"),
130 fn stdin_init() -> Arc
<Mutex
<BufReader
<StdinRaw
>>> {
131 // The default buffer capacity is 64k, but apparently windows
132 // doesn't like 64k reads on stdin. See #13304 for details, but the
133 // idea is that on windows we use a slightly smaller buffer that's
134 // been seen to be acceptable.
135 Arc
::new(Mutex
::new(if cfg
!(windows
) {
136 BufReader
::with_capacity(8 * 1024, stdin_raw())
138 BufReader
::new(stdin_raw())
144 /// Locks this handle to the standard input stream, returning a readable
147 /// The lock is released when the returned lock goes out of scope. The
148 /// returned guard also implements the `Read` and `BufRead` traits for
149 /// accessing the underlying data.
150 #[stable(feature = "rust1", since = "1.0.0")]
151 pub fn lock(&self) -> StdinLock
{
152 StdinLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) }
155 /// Locks this handle and reads a line of input into the specified buffer.
157 /// For detailed semantics of this method, see the documentation on
158 /// `BufRead::read_line`.
159 #[stable(feature = "rust1", since = "1.0.0")]
160 pub fn read_line(&mut self, buf
: &mut String
) -> io
::Result
<usize> {
161 self.lock().read_line(buf
)
165 #[stable(feature = "rust1", since = "1.0.0")]
166 impl Read
for Stdin
{
167 fn read(&mut self, buf
: &mut [u8]) -> io
::Result
<usize> {
168 self.lock().read(buf
)
170 fn read_to_end(&mut self, buf
: &mut Vec
<u8>) -> io
::Result
<usize> {
171 self.lock().read_to_end(buf
)
173 fn read_to_string(&mut self, buf
: &mut String
) -> io
::Result
<usize> {
174 self.lock().read_to_string(buf
)
178 #[stable(feature = "rust1", since = "1.0.0")]
179 impl<'a
> Read
for StdinLock
<'a
> {
180 fn read(&mut self, buf
: &mut [u8]) -> io
::Result
<usize> {
184 #[stable(feature = "rust1", since = "1.0.0")]
185 impl<'a
> BufRead
for StdinLock
<'a
> {
186 fn fill_buf(&mut self) -> io
::Result
<&[u8]> { self.inner.fill_buf() }
187 fn consume(&mut self, n
: usize) { self.inner.consume(n) }
190 // As with stdin on windows, stdout often can't handle writes of large
191 // sizes. For an example, see #14940. For this reason, don't try to
192 // write the entire output buffer on windows. On unix we can just
193 // write the whole buffer all at once.
195 // For some other references, it appears that this problem has been
196 // encountered by others [1] [2]. We choose the number 8KB just because
197 // libuv does the same.
199 // [1]: https://tahoe-lafs.org/trac/tahoe-lafs/ticket/1232
200 // [2]: http://www.mail-archive.com/log4net-dev@logging.apache.org/msg00661.html
202 const OUT_MAX
: usize = 8192;
204 const OUT_MAX
: usize = ::usize::MAX
;
206 /// A handle to the global standard output stream of the current process.
208 /// Each handle shares a global buffer of data to be written to the standard
209 /// output stream. Access is also synchronized via a lock and explicit control
210 /// over locking is available via the `lock` method.
212 /// Created by the function `io::stdout()`.
213 #[stable(feature = "rust1", since = "1.0.0")]
215 // FIXME: this should be LineWriter or BufWriter depending on the state of
216 // stdout (tty or not). Note that if this is not line buffered it
217 // should also flush-on-panic or some form of flush-on-abort.
218 inner
: Arc
<ReentrantMutex
<RefCell
<LineWriter
<StdoutRaw
>>>>,
221 /// A locked reference to the a `Stdout` handle.
223 /// This handle implements the `Write` trait and is constructed via the `lock`
224 /// method on `Stdout`.
225 #[stable(feature = "rust1", since = "1.0.0")]
226 pub struct StdoutLock
<'a
> {
227 inner
: ReentrantMutexGuard
<'a
, RefCell
<LineWriter
<StdoutRaw
>>>,
230 /// Constructs a new reference to the standard output of the current process.
232 /// Each handle returned is a reference to a shared global buffer whose access
233 /// is synchronized via a mutex. Explicit control over synchronization is
234 /// provided via the `lock` method.
236 /// The returned handle implements the `Write` trait.
237 #[stable(feature = "rust1", since = "1.0.0")]
238 pub fn stdout() -> Stdout
{
239 static INSTANCE
: Lazy
<ReentrantMutex
<RefCell
<LineWriter
<StdoutRaw
>>>> = lazy_init
!(stdout_init
);
241 inner
: INSTANCE
.get().expect("cannot access stdout during shutdown"),
244 fn stdout_init() -> Arc
<ReentrantMutex
<RefCell
<LineWriter
<StdoutRaw
>>>> {
245 Arc
::new(ReentrantMutex
::new(RefCell
::new(LineWriter
::new(stdout_raw()))))
250 /// Locks this handle to the standard output stream, returning a writable
253 /// The lock is released when the returned lock goes out of scope. The
254 /// returned guard also implements the `Write` trait for writing data.
255 #[stable(feature = "rust1", since = "1.0.0")]
256 pub fn lock(&self) -> StdoutLock
{
257 StdoutLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) }
261 #[stable(feature = "rust1", since = "1.0.0")]
262 impl Write
for Stdout
{
263 fn write(&mut self, buf
: &[u8]) -> io
::Result
<usize> {
264 self.lock().write(buf
)
266 fn flush(&mut self) -> io
::Result
<()> {
269 fn write_all(&mut self, buf
: &[u8]) -> io
::Result
<()> {
270 self.lock().write_all(buf
)
272 fn write_fmt(&mut self, args
: fmt
::Arguments
) -> io
::Result
<()> {
273 self.lock().write_fmt(args
)
276 #[stable(feature = "rust1", since = "1.0.0")]
277 impl<'a
> Write
for StdoutLock
<'a
> {
278 fn write(&mut self, buf
: &[u8]) -> io
::Result
<usize> {
279 self.inner
.borrow_mut().write(&buf
[..cmp
::min(buf
.len(), OUT_MAX
)])
281 fn flush(&mut self) -> io
::Result
<()> {
282 self.inner
.borrow_mut().flush()
286 /// A handle to the standard error stream of a process.
288 /// For more information, see `stderr`
289 #[stable(feature = "rust1", since = "1.0.0")]
291 inner
: Arc
<ReentrantMutex
<RefCell
<StderrRaw
>>>,
294 /// A locked reference to the a `Stderr` handle.
296 /// This handle implements the `Write` trait and is constructed via the `lock`
297 /// method on `Stderr`.
298 #[stable(feature = "rust1", since = "1.0.0")]
299 pub struct StderrLock
<'a
> {
300 inner
: ReentrantMutexGuard
<'a
, RefCell
<StderrRaw
>>,
303 /// Constructs a new reference to the standard error stream of a process.
305 /// Each returned handle is synchronized amongst all other handles created from
306 /// this function. No handles are buffered, however.
308 /// The returned handle implements the `Write` trait.
309 #[stable(feature = "rust1", since = "1.0.0")]
310 pub fn stderr() -> Stderr
{
311 static INSTANCE
: Lazy
<ReentrantMutex
<RefCell
<StderrRaw
>>> = lazy_init
!(stderr_init
);
313 inner
: INSTANCE
.get().expect("cannot access stderr during shutdown"),
316 fn stderr_init() -> Arc
<ReentrantMutex
<RefCell
<StderrRaw
>>> {
317 Arc
::new(ReentrantMutex
::new(RefCell
::new(stderr_raw())))
322 /// Locks this handle to the standard error stream, returning a writable
325 /// The lock is released when the returned lock goes out of scope. The
326 /// returned guard also implements the `Write` trait for writing data.
327 #[stable(feature = "rust1", since = "1.0.0")]
328 pub fn lock(&self) -> StderrLock
{
329 StderrLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) }
333 #[stable(feature = "rust1", since = "1.0.0")]
334 impl Write
for Stderr
{
335 fn write(&mut self, buf
: &[u8]) -> io
::Result
<usize> {
336 self.lock().write(buf
)
338 fn flush(&mut self) -> io
::Result
<()> {
341 fn write_all(&mut self, buf
: &[u8]) -> io
::Result
<()> {
342 self.lock().write_all(buf
)
344 fn write_fmt(&mut self, args
: fmt
::Arguments
) -> io
::Result
<()> {
345 self.lock().write_fmt(args
)
348 #[stable(feature = "rust1", since = "1.0.0")]
349 impl<'a
> Write
for StderrLock
<'a
> {
350 fn write(&mut self, buf
: &[u8]) -> io
::Result
<usize> {
351 self.inner
.borrow_mut().write(&buf
[..cmp
::min(buf
.len(), OUT_MAX
)])
353 fn flush(&mut self) -> io
::Result
<()> {
354 self.inner
.borrow_mut().flush()
358 /// Resets the thread-local stderr handle to the specified writer
360 /// This will replace the current thread's stderr handle, returning the old
361 /// handle. All future calls to `panic!` and friends will emit their output to
362 /// this specified handle.
364 /// Note that this does not need to be called for all new threads; the default
365 /// output handle is to the process's stderr stream.
366 #[unstable(feature = "set_stdio",
367 reason
= "this function may disappear completely or be replaced \
368 with a more general mechanism")]
370 pub fn set_panic(sink
: Box
<Write
+ Send
>) -> Option
<Box
<Write
+ Send
>> {
371 use panicking
::LOCAL_STDERR
;
373 LOCAL_STDERR
.with(move |slot
| {
374 mem
::replace(&mut *slot
.borrow_mut(), Some(sink
))
375 }).and_then(|mut s
| {
381 /// Resets the thread-local stdout handle to the specified writer
383 /// This will replace the current thread's stdout handle, returning the old
384 /// handle. All future calls to `print!` and friends will emit their output to
385 /// this specified handle.
387 /// Note that this does not need to be called for all new threads; the default
388 /// output handle is to the process's stdout stream.
389 #[unstable(feature = "set_stdio",
390 reason
= "this function may disappear completely or be replaced \
391 with a more general mechanism")]
393 pub fn set_print(sink
: Box
<Write
+ Send
>) -> Option
<Box
<Write
+ Send
>> {
395 LOCAL_STDOUT
.with(move |slot
| {
396 mem
::replace(&mut *slot
.borrow_mut(), Some(sink
))
397 }).and_then(|mut s
| {
403 #[unstable(feature = "print",
404 reason
= "implementation detail which may disappear or be replaced at any time")]
406 pub fn _print(args
: fmt
::Arguments
) {
407 let result
= LOCAL_STDOUT
.with(|s
| {
408 if s
.borrow_state() == BorrowState
::Unused
{
409 if let Some(w
) = s
.borrow_mut().as_mut() {
410 return w
.write_fmt(args
);
413 stdout().write_fmt(args
)
415 if let Err(e
) = result
{
416 panic
!("failed printing to stdout: {}", e
);
426 fn panic_doesnt_poison() {
435 }).join().unwrap_err();