Skip to content

Commit 0f3c7d1

Browse files
pickfirejoshtriplett
andcommittedJun 12, 2021
Explain non-dropped sender recv in docs
Original senders that are still hanging around could cause Receiver::recv to not block since this is a potential footgun for beginners, clarify more on this in the docs for readers to be aware about it. Fix minor tidbits in sender recv doc Co-authored-by: Dylan DPC <[email protected]> Add example for unbounded receive loops in doc Show the drop(tx) pattern, based on tokio docs https://tokio-rs.github.io/tokio/doc/tokio/sync/index.html Fix example code for drop sender recv Fix wording in sender docs Co-authored-by: Josh Triplett <[email protected]>
1 parent 11c94a1 commit 0f3c7d1

File tree

1 file changed

+46
-7
lines changed
  • library/std/src/sync/mpsc

1 file changed

+46
-7
lines changed
 

‎library/std/src/sync/mpsc/mod.rs

+46-7
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,35 @@
105105
//! });
106106
//! rx.recv().unwrap();
107107
//! ```
108+
//!
109+
//! Unbounded receive loop:
110+
//!
111+
//! ```
112+
//! use std::sync::mpsc::sync_channel;
113+
//! use std::thread;
114+
//!
115+
//! let (tx, rx) = sync_channel(3);
116+
//!
117+
//! for _ in 0..3 {
118+
//! // It would be the same without thread and clone here
119+
//! // since there will still be one `tx` left.
120+
//! let tx = tx.clone();
121+
//! // cloned tx dropped within thread
122+
//! thread::spawn(move || tx.send("ok").unwrap());
123+
//! }
124+
//!
125+
//! // Drop the last sender to stop `rx` waiting for message.
126+
//! // The program will not complete if we comment this out.
127+
//! // **All** `tx` needs to be dropped for `rx` to have `Err`.
128+
//! drop(tx);
129+
//!
130+
//! // Unbounded receiver waiting for all senders to complete.
131+
//! while let Ok(msg) = rx.recv() {
132+
//! println!("{}", msg);
133+
//! }
134+
//!
135+
//! println!("completed");
136+
//! ```
108137
109138
#![stable(feature = "rust1", since = "1.0.0")]
110139

@@ -436,6 +465,9 @@ pub struct IntoIter<T> {
436465
///
437466
/// Messages can be sent through this channel with [`send`].
438467
///
468+
/// Note: all senders (the original and the clones) need to be dropped for the receiver
469+
/// to stop blocking to receive messages with [`Receiver::recv`].
470+
///
439471
/// [`send`]: Sender::send
440472
///
441473
/// # Examples
@@ -642,7 +674,7 @@ impl<T> UnsafeFlavor<T> for Receiver<T> {
642674
/// the same order as it was sent, and no [`send`] will block the calling thread
643675
/// (this channel has an "infinite buffer", unlike [`sync_channel`], which will
644676
/// block after its buffer limit is reached). [`recv`] will block until a message
645-
/// is available.
677+
/// is available while there is at least one [`Sender`] alive (including clones).
646678
///
647679
/// The [`Sender`] can be cloned to [`send`] to the same channel multiple times, but
648680
/// only one [`Receiver`] is supported.
@@ -805,6 +837,11 @@ impl<T> Sender<T> {
805837

806838
#[stable(feature = "rust1", since = "1.0.0")]
807839
impl<T> Clone for Sender<T> {
840+
/// Clone a sender to send to other threads.
841+
///
842+
/// Note, be aware of the lifetime of the sender because all senders
843+
/// (including the original) need to be dropped in order for
844+
/// [`Receiver::recv`] to stop blocking.
808845
fn clone(&self) -> Sender<T> {
809846
let packet = match *unsafe { self.inner() } {
810847
Flavor::Oneshot(ref p) => {
@@ -1063,9 +1100,10 @@ impl<T> Receiver<T> {
10631100
/// corresponding channel has hung up.
10641101
///
10651102
/// This function will always block the current thread if there is no data
1066-
/// available and it's possible for more data to be sent. Once a message is
1067-
/// sent to the corresponding [`Sender`] (or [`SyncSender`]), then this
1068-
/// receiver will wake up and return that message.
1103+
/// available and it's possible for more data to be sent (at least one sender
1104+
/// still exists). Once a message is sent to the corresponding [`Sender`]
1105+
/// (or [`SyncSender`]), this receiver will wake up and return that
1106+
/// message.
10691107
///
10701108
/// If the corresponding [`Sender`] has disconnected, or it disconnects while
10711109
/// this call is blocking, this call will wake up and return [`Err`] to
@@ -1145,9 +1183,10 @@ impl<T> Receiver<T> {
11451183
/// corresponding channel has hung up, or if it waits more than `timeout`.
11461184
///
11471185
/// This function will always block the current thread if there is no data
1148-
/// available and it's possible for more data to be sent. Once a message is
1149-
/// sent to the corresponding [`Sender`] (or [`SyncSender`]), then this
1150-
/// receiver will wake up and return that message.
1186+
/// available and it's possible for more data to be sent (at least one sender
1187+
/// still exists). Once a message is sent to the corresponding [`Sender`]
1188+
/// (or [`SyncSender`]), this receiver will wake up and return that
1189+
/// message.
11511190
///
11521191
/// If the corresponding [`Sender`] has disconnected, or it disconnects while
11531192
/// this call is blocking, this call will wake up and return [`Err`] to

0 commit comments

Comments
 (0)