@@ -310,6 +310,48 @@ pub fn stdin() -> Stdin {
310
310
}
311
311
}
312
312
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
+
313
355
impl Stdin {
314
356
/// Locks this handle to the standard input stream, returning a readable
315
357
/// guard.
@@ -334,7 +376,7 @@ impl Stdin {
334
376
/// ```
335
377
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
336
378
pub fn lock ( & self ) -> StdinLock < ' _ > {
337
- StdinLock { inner : self . inner . lock ( ) . unwrap_or_else ( |e| e . into_inner ( ) ) }
379
+ self . lock_any ( )
338
380
}
339
381
340
382
/// Locks this handle and reads a line of input, appending it to the specified buffer.
@@ -367,6 +409,43 @@ impl Stdin {
367
409
pub fn read_line ( & self , buf : & mut String ) -> io:: Result < usize > {
368
410
self . lock ( ) . read_line ( buf)
369
411
}
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
+ }
370
449
}
371
450
372
451
#[ stable( feature = "std_debug" , since = "1.16.0" ) ]
@@ -558,6 +637,42 @@ pub fn stdout() -> Stdout {
558
637
}
559
638
}
560
639
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
+
561
676
pub fn cleanup ( ) {
562
677
if let Some ( instance) = STDOUT . get ( ) {
563
678
// Flush the data and disable buffering during shutdown
@@ -595,8 +710,45 @@ impl Stdout {
595
710
/// ```
596
711
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
597
712
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 > {
598
720
StdoutLock { inner : self . inner . lock ( ) }
599
721
}
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
+ }
600
752
}
601
753
602
754
#[ stable( feature = "std_debug" , since = "1.16.0" ) ]
@@ -769,6 +921,35 @@ pub fn stderr() -> Stderr {
769
921
}
770
922
}
771
923
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
+
772
953
impl Stderr {
773
954
/// Locks this handle to the standard error stream, returning a writable
774
955
/// guard.
@@ -792,8 +973,42 @@ impl Stderr {
792
973
/// ```
793
974
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
794
975
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 > {
795
983
StderrLock { inner : self . inner . lock ( ) }
796
984
}
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
+ }
797
1012
}
798
1013
799
1014
#[ stable( feature = "std_debug" , since = "1.16.0" ) ]
0 commit comments