]> git.lizzy.rs Git - rust.git/commitdiff
Explain non-dropped sender recv in docs
authorIvan Tham <pickfire@riseup.net>
Mon, 21 Dec 2020 18:16:01 +0000 (02:16 +0800)
committerIvan Tham <pickfire@riseup.net>
Sat, 12 Jun 2021 06:56:46 +0000 (14:56 +0800)
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 <dylan.dpc@gmail.com>
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 <josh@joshtriplett.org>
library/std/src/sync/mpsc/mod.rs

index db0777ee9f080b88d2fae091e789bfd2c3bd6d41..0465a19a47817e435bb17ee6d9dd2330d463e3f5 100644 (file)
 //! });
 //! rx.recv().unwrap();
 //! ```
+//!
+//! Unbounded receive loop:
+//!
+//! ```
+//! use std::sync::mpsc::sync_channel;
+//! use std::thread;
+//!
+//! let (tx, rx) = sync_channel(3);
+//!
+//! for _ in 0..3 {
+//!     // It would be the same without thread and clone here
+//!     // since there will still be one `tx` left.
+//!     let tx = tx.clone();
+//!     // cloned tx dropped within thread
+//!     thread::spawn(move || tx.send("ok").unwrap());
+//! }
+//!
+//! // Drop the last sender to stop `rx` waiting for message.
+//! // The program will not complete if we comment this out.
+//! // **All** `tx` needs to be dropped for `rx` to have `Err`.
+//! drop(tx);
+//!
+//! // Unbounded receiver waiting for all senders to complete.
+//! while let Ok(msg) = rx.recv() {
+//!     println!("{}", msg);
+//! }
+//!
+//! println!("completed");
+//! ```
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
@@ -436,6 +465,9 @@ pub struct IntoIter<T> {
 ///
 /// Messages can be sent through this channel with [`send`].
 ///
+/// Note: all senders (the original and the clones) need to be dropped for the receiver
+/// to stop blocking to receive messages with [`Receiver::recv`].
+///
 /// [`send`]: Sender::send
 ///
 /// # Examples
@@ -642,7 +674,7 @@ fn inner_unsafe(&self) -> &UnsafeCell<Flavor<T>> {
 /// the same order as it was sent, and no [`send`] will block the calling thread
 /// (this channel has an "infinite buffer", unlike [`sync_channel`], which will
 /// block after its buffer limit is reached). [`recv`] will block until a message
-/// is available.
+/// is available while there is at least one [`Sender`] alive (including clones).
 ///
 /// The [`Sender`] can be cloned to [`send`] to the same channel multiple times, but
 /// only one [`Receiver`] is supported.
@@ -805,6 +837,11 @@ pub fn send(&self, t: T) -> Result<(), SendError<T>> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Clone for Sender<T> {
+    /// Clone a sender to send to other threads.
+    ///
+    /// Note, be aware of the lifetime of the sender because all senders
+    /// (including the original) need to be dropped in order for
+    /// [`Receiver::recv`] to stop blocking.
     fn clone(&self) -> Sender<T> {
         let packet = match *unsafe { self.inner() } {
             Flavor::Oneshot(ref p) => {
@@ -1063,9 +1100,10 @@ pub fn try_recv(&self) -> Result<T, TryRecvError> {
     /// corresponding channel has hung up.
     ///
     /// This function will always block the current thread if there is no data
-    /// available and it's possible for more data to be sent. Once a message is
-    /// sent to the corresponding [`Sender`] (or [`SyncSender`]), then this
-    /// receiver will wake up and return that message.
+    /// available and it's possible for more data to be sent (at least one sender
+    /// still exists). Once a message is sent to the corresponding [`Sender`]
+    /// (or [`SyncSender`]), this receiver will wake up and return that
+    /// message.
     ///
     /// If the corresponding [`Sender`] has disconnected, or it disconnects while
     /// this call is blocking, this call will wake up and return [`Err`] to
@@ -1145,9 +1183,10 @@ pub fn recv(&self) -> Result<T, RecvError> {
     /// corresponding channel has hung up, or if it waits more than `timeout`.
     ///
     /// This function will always block the current thread if there is no data
-    /// available and it's possible for more data to be sent. Once a message is
-    /// sent to the corresponding [`Sender`] (or [`SyncSender`]), then this
-    /// receiver will wake up and return that message.
+    /// available and it's possible for more data to be sent (at least one sender
+    /// still exists). Once a message is sent to the corresponding [`Sender`]
+    /// (or [`SyncSender`]), this receiver will wake up and return that
+    /// message.
     ///
     /// If the corresponding [`Sender`] has disconnected, or it disconnects while
     /// this call is blocking, this call will wake up and return [`Err`] to