|
| 1 | +use std::io::Write as StdWrite; |
1 | 2 | use std::pin::Pin; |
2 | 3 | use std::sync::Mutex; |
3 | 4 |
|
4 | 5 | use crate::future::Future; |
5 | 6 | use crate::io::{self, Write}; |
6 | 7 | use crate::task::{spawn_blocking, Context, JoinHandle, Poll}; |
7 | 8 |
|
| 9 | +cfg_unstable! { |
| 10 | + use once_cell::sync::Lazy; |
| 11 | +} |
| 12 | + |
8 | 13 | /// Constructs a new handle to the standard output of the current process. |
9 | 14 | /// |
10 | 15 | /// This function is an async version of [`std::io::stdout`]. |
@@ -53,6 +58,16 @@ pub fn stdout() -> Stdout { |
53 | 58 | #[derive(Debug)] |
54 | 59 | pub struct Stdout(Mutex<State>); |
55 | 60 |
|
| 61 | +/// A locked reference to the Stderr handle. |
| 62 | +/// This handle implements the [`Write`] traits, and is constructed via the [`Stdout::lock`] method. |
| 63 | +/// |
| 64 | +/// [`Write`]: trait.Read.html |
| 65 | +/// [`Stdout::lock`]: struct.Stdout.html#method.lock |
| 66 | +#[derive(Debug)] |
| 67 | +pub struct StdoutLock<'a>(std::io::StdoutLock<'a>); |
| 68 | + |
| 69 | +unsafe impl Send for StdoutLock<'_> {} |
| 70 | + |
56 | 71 | /// The state of the asynchronous stdout. |
57 | 72 | /// |
58 | 73 | /// The stdout can be either idle or busy performing an asynchronous operation. |
@@ -87,6 +102,35 @@ enum Operation { |
87 | 102 | Flush(io::Result<()>), |
88 | 103 | } |
89 | 104 |
|
| 105 | +impl Stdout { |
| 106 | + /// Locks this handle to the standard error stream, returning a writable guard. |
| 107 | + /// |
| 108 | + /// The lock is released when the returned lock goes out of scope. The returned guard also implements the Write trait for writing data. |
| 109 | + /// |
| 110 | + /// # Examples |
| 111 | + /// |
| 112 | + /// ```no_run |
| 113 | + /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { |
| 114 | + /// # |
| 115 | + /// use async_std::io; |
| 116 | + /// use async_std::prelude::*; |
| 117 | + /// |
| 118 | + /// let stdout = io::stdout(); |
| 119 | + /// let mut handle = stdout.lock().await; |
| 120 | + /// |
| 121 | + /// handle.write_all(b"hello world").await?; |
| 122 | + /// # |
| 123 | + /// # Ok(()) }) } |
| 124 | + /// ``` |
| 125 | + #[cfg_attr(feature = "docs", doc(cfg(unstable)))] |
| 126 | + #[cfg(any(feature = "unstable", feature = "docs"))] |
| 127 | + pub async fn lock(&self) -> StdoutLock<'static> { |
| 128 | + static STDOUT: Lazy<std::io::Stdout> = Lazy::new(std::io::stdout); |
| 129 | + |
| 130 | + spawn_blocking(move || StdoutLock(STDOUT.lock())).await |
| 131 | + } |
| 132 | +} |
| 133 | + |
90 | 134 | impl Write for Stdout { |
91 | 135 | fn poll_write( |
92 | 136 | mut self: Pin<&mut Self>, |
@@ -189,3 +233,21 @@ cfg_windows! { |
189 | 233 | } |
190 | 234 | } |
191 | 235 | } |
| 236 | + |
| 237 | +impl Write for StdoutLock<'_> { |
| 238 | + fn poll_write( |
| 239 | + mut self: Pin<&mut Self>, |
| 240 | + _cx: &mut Context<'_>, |
| 241 | + buf: &[u8], |
| 242 | + ) -> Poll<io::Result<usize>> { |
| 243 | + Poll::Ready(self.0.write(buf)) |
| 244 | + } |
| 245 | + |
| 246 | + fn poll_flush(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<()>> { |
| 247 | + Poll::Ready(self.0.flush()) |
| 248 | + } |
| 249 | + |
| 250 | + fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> { |
| 251 | + self.poll_flush(cx) |
| 252 | + } |
| 253 | +} |
0 commit comments