@@ -310,6 +310,48 @@ pub fn stdin() -> Stdin {
310310 }
311311}
312312
313+ /// Constructs a new locked handle to the standard input of the current
314+ /// process.
315+ ///
316+ /// Each handle returned is a guard granting locked access to a shared
317+ /// global buffer whose access is synchronized via a mutex. If you need
318+ /// more explicit control over locking, for example, in a multi-threaded
319+ /// program, use the [`io::stdin`] function to obtain an unlocked handle,
320+ /// along with the [`Stdin::lock`] method.
321+ ///
322+ /// The lock is released when the returned guard goes out of scope. The
323+ /// returned guard also implements the [`Read`] and [`BufRead`] traits for
324+ /// accessing the underlying data.
325+ ///
326+ /// **Note**: The mutex locked by this handle is not reentrant. Even in a
327+ /// single-threaded program, calling other code that accesses [`Stdin`]
328+ /// could cause a deadlock or panic, if this locked handle is held across
329+ /// that call.
330+ ///
331+ /// ### Note: Windows Portability Consideration
332+ /// When operating in a console, the Windows implementation of this stream does not support
333+ /// non-UTF-8 byte sequences. Attempting to read bytes that are not valid UTF-8 will return
334+ /// an error.
335+ ///
336+ /// # Examples
337+ ///
338+ /// ```no_run
339+ /// #![feature(stdio_locked)]
340+ /// use std::io::{self, Read};
341+ ///
342+ /// fn main() -> io::Result<()> {
343+ /// let mut buffer = String::new();
344+ /// let mut handle = io::stdin_locked();
345+ ///
346+ /// handle.read_to_string(&mut buffer)?;
347+ /// Ok(())
348+ /// }
349+ /// ```
350+ #[ unstable( feature = "stdio_locked" , issue = "none" ) ]
351+ pub fn stdin_locked ( ) -> StdinLock < ' static > {
352+ stdin ( ) . into_locked ( )
353+ }
354+
313355impl Stdin {
314356 /// Locks this handle to the standard input stream, returning a readable
315357 /// guard.
@@ -334,7 +376,7 @@ impl Stdin {
334376 /// ```
335377 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
336378 pub fn lock ( & self ) -> StdinLock < ' _ > {
337- StdinLock { inner : self . inner . lock ( ) . unwrap_or_else ( |e| e . into_inner ( ) ) }
379+ self . lock_any ( )
338380 }
339381
340382 /// Locks this handle and reads a line of input, appending it to the specified buffer.
@@ -367,6 +409,43 @@ impl Stdin {
367409 pub fn read_line ( & self , buf : & mut String ) -> io:: Result < usize > {
368410 self . lock ( ) . read_line ( buf)
369411 }
412+
413+ // Locks this handle with any lifetime. This depends on the
414+ // implementation detail that the underlying `Mutex` is static.
415+ fn lock_any < ' a > ( & self ) -> StdinLock < ' a > {
416+ StdinLock { inner : self . inner . lock ( ) . unwrap_or_else ( |e| e. into_inner ( ) ) }
417+ }
418+
419+ /// Consumes this handle to the standard input stream, locking the
420+ /// shared global buffer associated with the stream and returning a
421+ /// readable guard.
422+ ///
423+ /// The lock is released when the returned guard goes out of scope. The
424+ /// returned guard also implements the [`Read`] and [`BufRead`] traits
425+ /// for accessing the underlying data.
426+ ///
427+ /// It is often simpler to directly get a locked handle using the
428+ /// [`stdin_locked`] function instead, unless nearby code also needs to
429+ /// use an unlocked handle.
430+ ///
431+ /// # Examples
432+ ///
433+ /// ```no_run
434+ /// #![feature(stdio_locked)]
435+ /// use std::io::{self, Read};
436+ ///
437+ /// fn main() -> io::Result<()> {
438+ /// let mut buffer = String::new();
439+ /// let mut handle = io::stdin().into_locked();
440+ ///
441+ /// handle.read_to_string(&mut buffer)?;
442+ /// Ok(())
443+ /// }
444+ /// ```
445+ #[ unstable( feature = "stdio_locked" , issue = "none" ) ]
446+ pub fn into_locked ( self ) -> StdinLock < ' static > {
447+ self . lock_any ( )
448+ }
370449}
371450
372451#[ stable( feature = "std_debug" , since = "1.16.0" ) ]
@@ -558,6 +637,42 @@ pub fn stdout() -> Stdout {
558637 }
559638}
560639
640+ /// Constructs a new locked handle to the standard output of the current
641+ /// process.
642+ ///
643+ /// Each handle returned is a guard granting locked access to a shared
644+ /// global buffer whose access is synchronized via a mutex. If you need
645+ /// more explicit control over locking, for example, in a multi-threaded
646+ /// program, use the [`io::stdout`] function to obtain an unlocked handle,
647+ /// along with the [`Stdout::lock`] method.
648+ ///
649+ /// The lock is released when the returned guard goes out of scope. The
650+ /// returned guard also implements the [`Write`] trait for writing data.
651+ ///
652+ /// ### Note: Windows Portability Consideration
653+ /// When operating in a console, the Windows implementation of this stream does not support
654+ /// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
655+ /// an error.
656+ ///
657+ /// # Examples
658+ ///
659+ /// ```no_run
660+ /// #![feature(stdio_locked)]
661+ /// use std::io::{self, Write};
662+ ///
663+ /// fn main() -> io::Result<()> {
664+ /// let mut handle = io::stdout_locked();
665+ ///
666+ /// handle.write_all(b"hello world")?;
667+ ///
668+ /// Ok(())
669+ /// }
670+ /// ```
671+ #[ unstable( feature = "stdio_locked" , issue = "none" ) ]
672+ pub fn stdout_locked ( ) -> StdoutLock < ' static > {
673+ stdout ( ) . into_locked ( )
674+ }
675+
561676pub fn cleanup ( ) {
562677 if let Some ( instance) = STDOUT . get ( ) {
563678 // Flush the data and disable buffering during shutdown
@@ -595,8 +710,45 @@ impl Stdout {
595710 /// ```
596711 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
597712 pub fn lock ( & self ) -> StdoutLock < ' _ > {
713+ self . lock_any ( )
714+ }
715+
716+ // Locks this handle with any lifetime. This depends on the
717+ // implementation detail that the underlying `ReentrantMutex` is
718+ // static.
719+ fn lock_any < ' a > ( & self ) -> StdoutLock < ' a > {
598720 StdoutLock { inner : self . inner . lock ( ) }
599721 }
722+
723+ /// Consumes this handle to the standard output stream, locking the
724+ /// shared global buffer associated with the stream and returning a
725+ /// writable guard.
726+ ///
727+ /// The lock is released when the returned lock goes out of scope. The
728+ /// returned guard also implements the [`Write`] trait for writing data.
729+ ///
730+ /// It is often simpler to directly get a locked handle using the
731+ /// [`io::stdout_locked`] function instead, unless nearby code also
732+ /// needs to use an unlocked handle.
733+ ///
734+ /// # Examples
735+ ///
736+ /// ```no_run
737+ /// #![feature(stdio_locked)]
738+ /// use std::io::{self, Write};
739+ ///
740+ /// fn main() -> io::Result<()> {
741+ /// let mut handle = io::stdout().into_locked();
742+ ///
743+ /// handle.write_all(b"hello world")?;
744+ ///
745+ /// Ok(())
746+ /// }
747+ /// ```
748+ #[ unstable( feature = "stdio_locked" , issue = "none" ) ]
749+ pub fn into_locked ( self ) -> StdoutLock < ' static > {
750+ self . lock_any ( )
751+ }
600752}
601753
602754#[ stable( feature = "std_debug" , since = "1.16.0" ) ]
@@ -769,6 +921,35 @@ pub fn stderr() -> Stderr {
769921 }
770922}
771923
924+ /// Constructs a new locked handle to the standard error of the current
925+ /// process.
926+ ///
927+ /// This handle is not buffered.
928+ ///
929+ /// ### Note: Windows Portability Consideration
930+ /// When operating in a console, the Windows implementation of this stream does not support
931+ /// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
932+ /// an error.
933+ ///
934+ /// # Example
935+ ///
936+ /// ```no_run
937+ /// #![feature(stdio_locked)]
938+ /// use std::io::{self, Write};
939+ ///
940+ /// fn main() -> io::Result<()> {
941+ /// let mut handle = io::stderr_locked();
942+ ///
943+ /// handle.write_all(b"hello world")?;
944+ ///
945+ /// Ok(())
946+ /// }
947+ /// ```
948+ #[ unstable( feature = "stdio_locked" , issue = "none" ) ]
949+ pub fn stderr_locked ( ) -> StderrLock < ' static > {
950+ stderr ( ) . into_locked ( )
951+ }
952+
772953impl Stderr {
773954 /// Locks this handle to the standard error stream, returning a writable
774955 /// guard.
@@ -792,8 +973,42 @@ impl Stderr {
792973 /// ```
793974 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
794975 pub fn lock ( & self ) -> StderrLock < ' _ > {
976+ self . lock_any ( )
977+ }
978+
979+ // Locks this handle with any lifetime. This depends on the
980+ // implementation detail that the underlying `ReentrantMutex` is
981+ // static.
982+ fn lock_any < ' a > ( & self ) -> StderrLock < ' a > {
795983 StderrLock { inner : self . inner . lock ( ) }
796984 }
985+
986+ /// Locks and consumes this handle to the standard error stream,
987+ /// returning a writable guard.
988+ ///
989+ /// The lock is released when the returned guard goes out of scope. The
990+ /// returned guard also implements the [`Write`] trait for writing
991+ /// data.
992+ ///
993+ /// # Examples
994+ ///
995+ /// ```
996+ /// #![feature(stdio_locked)]
997+ /// use std::io::{self, Write};
998+ ///
999+ /// fn foo() -> io::Result<()> {
1000+ /// let stderr = io::stderr();
1001+ /// let mut handle = stderr.into_locked();
1002+ ///
1003+ /// handle.write_all(b"hello world")?;
1004+ ///
1005+ /// Ok(())
1006+ /// }
1007+ /// ```
1008+ #[ unstable( feature = "stdio_locked" , issue = "none" ) ]
1009+ pub fn into_locked ( self ) -> StderrLock < ' static > {
1010+ self . lock_any ( )
1011+ }
7971012}
7981013
7991014#[ stable( feature = "std_debug" , since = "1.16.0" ) ]
0 commit comments