Skip to content

Commit 752d48d

Browse files
matthiaskrgrgitbot
authored and
gitbot
committed
Rollup merge of rust-lang#133986 - olishmollie:tracking-issue-127154-documentation, r=tgross35
Add documentation for anonymous pipe module Tracking issue: rust-lang#127154 `@NobodyXu` I've been using this feature lately and thought I might contribute with some documentation. I borrowed liberally from [os_pipe](https://docs.rs/os_pipe/latest/os_pipe/) so thanks to `@oconnor663.`
2 parents 5216be9 + 7716936 commit 752d48d

File tree

1 file changed

+135
-5
lines changed

1 file changed

+135
-5
lines changed

std/src/pipe.rs

+135-5
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,66 @@
1-
//! Module for anonymous pipe
1+
//! A cross-platform anonymous pipe.
22
//!
3-
//! ```
4-
//! #![feature(anonymous_pipe)]
3+
//! This module provides support for anonymous OS pipes, like [pipe] on Linux or [CreatePipe] on
4+
//! Windows.
5+
//!
6+
//! # Behavior
7+
//!
8+
//! A pipe is a synchronous, unidirectional data channel between two or more processes, like an
9+
//! interprocess [`mpsc`](crate::sync::mpsc) provided by the OS. In particular:
10+
//!
11+
//! * A read on a [`PipeReader`] blocks until the pipe is non-empty.
12+
//! * A write on a [`PipeWriter`] blocks when the pipe is full.
13+
//! * When all copies of a [`PipeWriter`] are closed, a read on the corresponding [`PipeReader`]
14+
//! returns EOF.
15+
//! * [`PipeReader`] can be shared, but only one process will consume the data in the pipe.
16+
//!
17+
//! # Capacity
18+
//!
19+
//! Pipe capacity is platform dependent. To quote the Linux [man page]:
20+
//!
21+
//! > Different implementations have different limits for the pipe capacity. Applications should
22+
//! > not rely on a particular capacity: an application should be designed so that a reading process
23+
//! > consumes data as soon as it is available, so that a writing process does not remain blocked.
524
//!
25+
//! # Examples
26+
//!
27+
//! ```no_run
28+
//! #![feature(anonymous_pipe)]
629
//! # #[cfg(miri)] fn main() {}
730
//! # #[cfg(not(miri))]
831
//! # fn main() -> std::io::Result<()> {
9-
//! let (reader, writer) = std::pipe::pipe()?;
32+
//! # use std::process::Command;
33+
//! # use std::io::{Read, Write};
34+
//! let (ping_rx, mut ping_tx) = std::pipe::pipe()?;
35+
//! let (mut pong_rx, pong_tx) = std::pipe::pipe()?;
36+
//!
37+
//! // Spawn a process that echoes its input.
38+
//! let mut echo_server = Command::new("cat").stdin(ping_rx).stdout(pong_tx).spawn()?;
39+
//!
40+
//! ping_tx.write_all(b"hello")?;
41+
//! // Close to unblock echo_server's reader.
42+
//! drop(ping_tx);
43+
//!
44+
//! let mut buf = String::new();
45+
//! // Block until echo_server's writer is closed.
46+
//! pong_rx.read_to_string(&mut buf)?;
47+
//! assert_eq!(&buf, "hello");
48+
//!
49+
//! echo_server.wait()?;
1050
//! # Ok(())
1151
//! # }
1252
//! ```
13-
53+
//! [pipe]: https://man7.org/linux/man-pages/man2/pipe.2.html
54+
//! [CreatePipe]: https://learn.microsoft.com/en-us/windows/win32/api/namedpipeapi/nf-namedpipeapi-createpipe
55+
//! [man page]: https://man7.org/linux/man-pages/man7/pipe.7.html
1456
use crate::io;
1557
use crate::sys::anonymous_pipe::{AnonPipe, pipe as pipe_inner};
1658

1759
/// Create anonymous pipe that is close-on-exec and blocking.
60+
///
61+
/// # Examples
62+
///
63+
/// See the [module-level](crate::pipe) documentation for examples.
1864
#[unstable(feature = "anonymous_pipe", issue = "127154")]
1965
#[inline]
2066
pub fn pipe() -> io::Result<(PipeReader, PipeWriter)> {
@@ -33,6 +79,58 @@ pub struct PipeWriter(pub(crate) AnonPipe);
3379

3480
impl PipeReader {
3581
/// Create a new [`PipeReader`] instance that shares the same underlying file description.
82+
///
83+
/// # Examples
84+
///
85+
/// ```no_run
86+
/// #![feature(anonymous_pipe)]
87+
/// # #[cfg(miri)] fn main() {}
88+
/// # #[cfg(not(miri))]
89+
/// # fn main() -> std::io::Result<()> {
90+
/// # use std::fs;
91+
/// # use std::io::Write;
92+
/// # use std::process::Command;
93+
/// const NUM_SLOT: u8 = 2;
94+
/// const NUM_PROC: u8 = 5;
95+
/// const OUTPUT: &str = "work.txt";
96+
///
97+
/// let mut jobs = vec![];
98+
/// let (reader, mut writer) = std::pipe::pipe()?;
99+
///
100+
/// // Write NUM_SLOT characters the the pipe.
101+
/// writer.write_all(&[b'|'; NUM_SLOT as usize])?;
102+
///
103+
/// // Spawn several processes that read a character from the pipe, do some work, then
104+
/// // write back to the pipe. When the pipe is empty, the processes block, so only
105+
/// // NUM_SLOT processes can be working at any given time.
106+
/// for _ in 0..NUM_PROC {
107+
/// jobs.push(
108+
/// Command::new("bash")
109+
/// .args(["-c",
110+
/// &format!(
111+
/// "read -n 1\n\
112+
/// echo -n 'x' >> '{OUTPUT}'\n\
113+
/// echo -n '|'",
114+
/// ),
115+
/// ])
116+
/// .stdin(reader.try_clone()?)
117+
/// .stdout(writer.try_clone()?)
118+
/// .spawn()?,
119+
/// );
120+
/// }
121+
///
122+
/// // Wait for all jobs to finish.
123+
/// for mut job in jobs {
124+
/// job.wait()?;
125+
/// }
126+
///
127+
/// // Check our work and clean up.
128+
/// let xs = fs::read_to_string(OUTPUT)?;
129+
/// fs::remove_file(OUTPUT)?;
130+
/// assert_eq!(xs, "x".repeat(NUM_PROC.into()));
131+
/// # Ok(())
132+
/// # }
133+
/// ```
36134
#[unstable(feature = "anonymous_pipe", issue = "127154")]
37135
pub fn try_clone(&self) -> io::Result<Self> {
38136
self.0.try_clone().map(Self)
@@ -41,6 +139,38 @@ impl PipeReader {
41139

42140
impl PipeWriter {
43141
/// Create a new [`PipeWriter`] instance that shares the same underlying file description.
142+
///
143+
/// # Examples
144+
///
145+
/// ```no_run
146+
/// #![feature(anonymous_pipe)]
147+
/// # #[cfg(miri)] fn main() {}
148+
/// # #[cfg(not(miri))]
149+
/// # fn main() -> std::io::Result<()> {
150+
/// # use std::process::Command;
151+
/// # use std::io::Read;
152+
/// let (mut reader, writer) = std::pipe::pipe()?;
153+
///
154+
/// // Spawn a process that writes to stdout and stderr.
155+
/// let mut peer = Command::new("bash")
156+
/// .args([
157+
/// "-c",
158+
/// "echo -n foo\n\
159+
/// echo -n bar >&2"
160+
/// ])
161+
/// .stdout(writer.try_clone()?)
162+
/// .stderr(writer)
163+
/// .spawn()?;
164+
///
165+
/// // Read and check the result.
166+
/// let mut msg = String::new();
167+
/// reader.read_to_string(&mut msg)?;
168+
/// assert_eq!(&msg, "foobar");
169+
///
170+
/// peer.wait()?;
171+
/// # Ok(())
172+
/// # }
173+
/// ```
44174
#[unstable(feature = "anonymous_pipe", issue = "127154")]
45175
pub fn try_clone(&self) -> io::Result<Self> {
46176
self.0.try_clone().map(Self)

0 commit comments

Comments
 (0)