@@ -261,6 +261,21 @@ pub struct StdinLock<'a> {
261
261
inner : MutexGuard < ' a , BufReader < StdinRaw > > ,
262
262
}
263
263
264
+ /// Owned locked [`Stdin`] handle, returned by [`Stdin::into_lock`] and
265
+ /// [`io::stdin_locked`].
266
+ ///
267
+ /// This is exactly like [`StdinLock`], except that it can outlive the
268
+ /// [`Stdin`] handle that was used to create it. See the [`StdinLock`]
269
+ /// documentation for more details.
270
+ ///
271
+ /// ### Note: Windows Portability Consideration
272
+ ///
273
+ /// When operating in a console, the Windows implementation of this stream does not support
274
+ /// non-UTF-8 byte sequences. Attempting to read bytes that are not valid UTF-8 will return
275
+ /// an error.
276
+ #[ unstable( feature = "stdio_locked" , issue = "none" ) ]
277
+ pub type StdinOwnedLock = StdinLock < ' static > ;
278
+
264
279
/// Constructs a new handle to the standard input of the current process.
265
280
///
266
281
/// Each handle returned is a reference to a shared global buffer whose access
@@ -310,6 +325,48 @@ pub fn stdin() -> Stdin {
310
325
}
311
326
}
312
327
328
+ /// Constructs a new locked handle to the standard input of the current
329
+ /// process.
330
+ ///
331
+ /// Each handle returned is a guard granting locked access to a shared
332
+ /// global buffer whose access is synchronized via a mutex. If you need
333
+ /// more explicit control over locking, for example, in a multi-threaded
334
+ /// program, use the [`io::stdin`] function to obtain an unlocked handle,
335
+ /// along with the [`Stdin::lock`] method.
336
+ ///
337
+ /// The lock is released when the returned guard goes out of scope. The
338
+ /// returned guard also implements the [`Read`] and [`BufRead`] traits for
339
+ /// accessing the underlying data.
340
+ ///
341
+ /// **Note**: The mutex locked by this handle is not reentrant. Even in a
342
+ /// single-threaded program, calling other code that accesses [`Stdin`]
343
+ /// could cause a deadlock or panic, if this locked handle is held across
344
+ /// that call.
345
+ ///
346
+ /// ### Note: Windows Portability Consideration
347
+ /// When operating in a console, the Windows implementation of this stream does not support
348
+ /// non-UTF-8 byte sequences. Attempting to read bytes that are not valid UTF-8 will return
349
+ /// an error.
350
+ ///
351
+ /// # Examples
352
+ ///
353
+ /// ```no_run
354
+ /// #![feature(stdio_locked)]
355
+ /// use std::io::{self, Read};
356
+ ///
357
+ /// fn main() -> io::Result<()> {
358
+ /// let mut buffer = String::new();
359
+ /// let mut handle = io::stdin_locked();
360
+ ///
361
+ /// handle.read_to_string(&mut buffer)?;
362
+ /// Ok(())
363
+ /// }
364
+ /// ```
365
+ #[ unstable( feature = "stdio_locked" , issue = "none" ) ]
366
+ pub fn stdin_locked ( ) -> StdinOwnedLock {
367
+ stdin ( ) . into_lock ( )
368
+ }
369
+
313
370
impl Stdin {
314
371
/// Locks this handle to the standard input stream, returning a readable
315
372
/// guard.
@@ -334,7 +391,7 @@ impl Stdin {
334
391
/// ```
335
392
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
336
393
pub fn lock ( & self ) -> StdinLock < ' _ > {
337
- StdinLock { inner : self . inner . lock ( ) . unwrap_or_else ( |e| e . into_inner ( ) ) }
394
+ self . lock_any ( )
338
395
}
339
396
340
397
/// Locks this handle and reads a line of input, appending it to the specified buffer.
@@ -367,6 +424,43 @@ impl Stdin {
367
424
pub fn read_line ( & self , buf : & mut String ) -> io:: Result < usize > {
368
425
self . lock ( ) . read_line ( buf)
369
426
}
427
+
428
+ // Locks this handle with any lifetime. This depends on the
429
+ // implementation detail that the underlying `Mutex` is static.
430
+ fn lock_any < ' a > ( & self ) -> StdinLock < ' a > {
431
+ StdinLock { inner : self . inner . lock ( ) . unwrap_or_else ( |e| e. into_inner ( ) ) }
432
+ }
433
+
434
+ /// Consumes this handle to the standard input stream, locking the
435
+ /// shared global buffer associated with the stream and returning a
436
+ /// readable guard.
437
+ ///
438
+ /// The lock is released when the returned guard goes out of scope. The
439
+ /// returned guard also implements the [`Read`] and [`BufRead`] traits
440
+ /// for accessing the underlying data.
441
+ ///
442
+ /// It is often simpler to directly get a locked handle using the
443
+ /// [`stdin_locked`] function instead, unless nearby code also needs to
444
+ /// use an unlocked handle.
445
+ ///
446
+ /// # Examples
447
+ ///
448
+ /// ```no_run
449
+ /// #![feature(stdio_locked)]
450
+ /// use std::io::{self, Read};
451
+ ///
452
+ /// fn main() -> io::Result<()> {
453
+ /// let mut buffer = String::new();
454
+ /// let mut handle = io::stdin().into_lock();
455
+ ///
456
+ /// handle.read_to_string(&mut buffer)?;
457
+ /// Ok(())
458
+ /// }
459
+ /// ```
460
+ #[ unstable( feature = "stdio_locked" , issue = "none" ) ]
461
+ pub fn into_lock ( self ) -> StdinOwnedLock {
462
+ self . lock_any ( )
463
+ }
370
464
}
371
465
372
466
#[ stable( feature = "std_debug" , since = "1.16.0" ) ]
@@ -507,6 +601,20 @@ pub struct StdoutLock<'a> {
507
601
inner : ReentrantMutexGuard < ' a , RefCell < LineWriter < StdoutRaw > > > ,
508
602
}
509
603
604
+ /// Owned locked [`Stdout`] handle, returned by [`Stdout::into_lock`] and
605
+ /// [`io::stdout_locked`].
606
+ ///
607
+ /// This is exactly like [`StdoutLock`], except that it can outlive the
608
+ /// [`Stdout`] handle that was used to create it. See the [`StdoutLock`]
609
+ /// documentation for more details.
610
+ ///
611
+ /// ### Note: Windows Portability Consideration
612
+ /// When operating in a console, the Windows implementation of this stream does not support
613
+ /// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
614
+ /// an error.
615
+ #[ unstable( feature = "stdio_locked" , issue = "none" ) ]
616
+ pub type StdoutOwnedLock = StdoutLock < ' static > ;
617
+
510
618
static STDOUT : SyncOnceCell < ReentrantMutex < RefCell < LineWriter < StdoutRaw > > > > = SyncOnceCell :: new ( ) ;
511
619
512
620
/// Constructs a new handle to the standard output of the current process.
@@ -558,6 +666,42 @@ pub fn stdout() -> Stdout {
558
666
}
559
667
}
560
668
669
+ /// Constructs a new locked handle to the standard output of the current
670
+ /// process.
671
+ ///
672
+ /// Each handle returned is a guard granting locked access to a shared
673
+ /// global buffer whose access is synchronized via a mutex. If you need
674
+ /// more explicit control over locking, for example, in a multi-threaded
675
+ /// program, use the [`io::stdout`] function to obtain an unlocked handle,
676
+ /// along with the [`Stdout::lock`] method.
677
+ ///
678
+ /// The lock is released when the returned guard goes out of scope. The
679
+ /// returned guard also implements the [`Write`] trait for writing data.
680
+ ///
681
+ /// ### Note: Windows Portability Consideration
682
+ /// When operating in a console, the Windows implementation of this stream does not support
683
+ /// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
684
+ /// an error.
685
+ ///
686
+ /// # Examples
687
+ ///
688
+ /// ```no_run
689
+ /// #![feature(stdio_locked)]
690
+ /// use std::io::{self, Write};
691
+ ///
692
+ /// fn main() -> io::Result<()> {
693
+ /// let mut handle = io::stdout_locked();
694
+ ///
695
+ /// handle.write_all(b"hello world")?;
696
+ ///
697
+ /// Ok(())
698
+ /// }
699
+ /// ```
700
+ #[ unstable( feature = "stdio_locked" , issue = "none" ) ]
701
+ pub fn stdout_locked ( ) -> StdoutLock < ' static > {
702
+ stdout ( ) . into_lock ( )
703
+ }
704
+
561
705
pub fn cleanup ( ) {
562
706
if let Some ( instance) = STDOUT . get ( ) {
563
707
// Flush the data and disable buffering during shutdown
@@ -595,8 +739,45 @@ impl Stdout {
595
739
/// ```
596
740
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
597
741
pub fn lock ( & self ) -> StdoutLock < ' _ > {
742
+ self . lock_any ( )
743
+ }
744
+
745
+ // Locks this handle with any lifetime. This depends on the
746
+ // implementation detail that the underlying `ReentrantMutex` is
747
+ // static.
748
+ fn lock_any < ' a > ( & self ) -> StdoutLock < ' a > {
598
749
StdoutLock { inner : self . inner . lock ( ) }
599
750
}
751
+
752
+ /// Consumes this handle to the standard output stream, locking the
753
+ /// shared global buffer associated with the stream and returning a
754
+ /// writable guard.
755
+ ///
756
+ /// The lock is released when the returned lock goes out of scope. The
757
+ /// returned guard also implements the [`Write`] trait for writing data.
758
+ ///
759
+ /// It is often simpler to directly get a locked handle using the
760
+ /// [`io::stdout_locked`] function instead, unless nearby code also
761
+ /// needs to use an unlocked handle.
762
+ ///
763
+ /// # Examples
764
+ ///
765
+ /// ```no_run
766
+ /// #![feature(stdio_locked)]
767
+ /// use std::io::{self, Write};
768
+ ///
769
+ /// fn main() -> io::Result<()> {
770
+ /// let mut handle = io::stdout().into_lock();
771
+ ///
772
+ /// handle.write_all(b"hello world")?;
773
+ ///
774
+ /// Ok(())
775
+ /// }
776
+ /// ```
777
+ #[ unstable( feature = "stdio_locked" , issue = "none" ) ]
778
+ pub fn into_lock ( self ) -> StdoutOwnedLock {
779
+ self . lock_any ( )
780
+ }
600
781
}
601
782
602
783
#[ stable( feature = "std_debug" , since = "1.16.0" ) ]
@@ -717,6 +898,20 @@ pub struct StderrLock<'a> {
717
898
inner : ReentrantMutexGuard < ' a , RefCell < StderrRaw > > ,
718
899
}
719
900
901
+ /// Owned locked [`Stderr`] handle, returned by [`Stderr::into_lock`] and
902
+ /// [`io::stderr_locked`].
903
+ ///
904
+ /// This is exactly like [`StderrLock`], except that it can outlive the the
905
+ /// [`Stderr`] handle that was used to create it. See the [`StderrLock`]
906
+ /// documentation for more details.
907
+ ///
908
+ /// ### Note: Windows Portability Consideration
909
+ /// When operating in a console, the Windows implementation of this stream does not support
910
+ /// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
911
+ /// an error.
912
+ #[ unstable( feature = "stdio_locked" , issue = "none" ) ]
913
+ pub type StderrOwnedLock = StderrLock < ' static > ;
914
+
720
915
/// Constructs a new handle to the standard error of the current process.
721
916
///
722
917
/// This handle is not buffered.
@@ -769,6 +964,35 @@ pub fn stderr() -> Stderr {
769
964
}
770
965
}
771
966
967
+ /// Constructs a new locked handle to the standard error of the current
968
+ /// process.
969
+ ///
970
+ /// This handle is not buffered.
971
+ ///
972
+ /// ### Note: Windows Portability Consideration
973
+ /// When operating in a console, the Windows implementation of this stream does not support
974
+ /// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
975
+ /// an error.
976
+ ///
977
+ /// # Example
978
+ ///
979
+ /// ```no_run
980
+ /// #![feature(stdio_locked)]
981
+ /// use std::io::{self, Write};
982
+ ///
983
+ /// fn main() -> io::Result<()> {
984
+ /// let mut handle = io::stderr_locked();
985
+ ///
986
+ /// handle.write_all(b"hello world")?;
987
+ ///
988
+ /// Ok(())
989
+ /// }
990
+ /// ```
991
+ #[ unstable( feature = "stdio_locked" , issue = "none" ) ]
992
+ pub fn stderr_locked ( ) -> StderrOwnedLock {
993
+ stderr ( ) . into_lock ( )
994
+ }
995
+
772
996
impl Stderr {
773
997
/// Locks this handle to the standard error stream, returning a writable
774
998
/// guard.
@@ -792,8 +1016,42 @@ impl Stderr {
792
1016
/// ```
793
1017
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
794
1018
pub fn lock ( & self ) -> StderrLock < ' _ > {
1019
+ self . lock_any ( )
1020
+ }
1021
+
1022
+ // Locks this handle with any lifetime. This depends on the
1023
+ // implementation detail that the underlying `ReentrantMutex` is
1024
+ // static.
1025
+ fn lock_any < ' a > ( & self ) -> StderrLock < ' a > {
795
1026
StderrLock { inner : self . inner . lock ( ) }
796
1027
}
1028
+
1029
+ /// Locks and consumes this handle to the standard error stream,
1030
+ /// returning a writable guard.
1031
+ ///
1032
+ /// The lock is released when the returned guard goes out of scope. The
1033
+ /// returned guard also implements the [`Write`] trait for writing
1034
+ /// data.
1035
+ ///
1036
+ /// # Examples
1037
+ ///
1038
+ /// ```
1039
+ /// #![feature(stdio_locked)]
1040
+ /// use std::io::{self, Write};
1041
+ ///
1042
+ /// fn foo() -> io::Result<()> {
1043
+ /// let stderr = io::stderr();
1044
+ /// let mut handle = stderr.into_lock();
1045
+ ///
1046
+ /// handle.write_all(b"hello world")?;
1047
+ ///
1048
+ /// Ok(())
1049
+ /// }
1050
+ /// ```
1051
+ #[ unstable( feature = "stdio_locked" , issue = "none" ) ]
1052
+ pub fn into_lock ( self ) -> StderrOwnedLock {
1053
+ self . lock_any ( )
1054
+ }
797
1055
}
798
1056
799
1057
#[ stable( feature = "std_debug" , since = "1.16.0" ) ]
0 commit comments