Repository: rust-lang/rust
Pull request: Add is_disconnected functions to mpsc and mpmc channels

Add `is_disconnected()` functions to the `Sender` and `Receiver` of both `mpmc` an `mpsc` channels.

```rust
std::sync::mpmc::Sender<T>::is_disconnected(&self) -> bool
std::sync::mpmc::Receiver<T>::is_disconnected(&self) -> bool

std::sync::mpsc::Sender<T>::is_disconnected(&self) -> bool
std::sync::mpsc::Receiver<T>::is_disconnected(&self) -> bool
```

The `mpsc` methods are locked behind the `mpsc_is_disconnected` feature gate, which has no tracking issue yet.

ACP: https://github.com/rust-lang/libs-team/issues/748
Tracking issue: https://github.com/rust-lang/rust/issues/153668


Changed files:
filename: library/std/src/sync/mpmc/mod.rs
patch: @@ -623,6 +623,33 @@ impl<T> Sender<T> {
             _ => false,
         }
     }
+
+    /// Returns `true` if the channel is disconnected.
+    ///
+    /// Note that a return value of `false` does not guarantee the channel will
+    /// remain connected. The channel may be disconnected immediately after this method
+    /// returns, so a subsequent [`Sender::send`] may still fail with [`SendError`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(mpmc_channel)]
+    ///
+    /// use std::sync::mpmc::channel;
+    ///
+    /// let (tx, rx) = channel::<i32>();
+    /// assert!(!tx.is_disconnected());
+    /// drop(rx);
+    /// assert!(tx.is_disconnected());
+    /// ```
+    #[unstable(feature = "mpmc_channel", issue = "126840")]
+    pub fn is_disconnected(&self) -> bool {
+        match &self.flavor {
+            SenderFlavor::Array(chan) => chan.is_disconnected(),
+            SenderFlavor::List(chan) => chan.is_disconnected(),
+            SenderFlavor::Zero(chan) => chan.is_disconnected(),
+        }
+    }
 }
 
 #[unstable(feature = "mpmc_channel", issue = "126840")]
@@ -1349,6 +1376,33 @@ impl<T> Receiver<T> {
     pub fn iter(&self) -> Iter<'_, T> {
         Iter { rx: self }
     }
+
+    /// Returns `true` if the channel is disconnected.
+    ///
+    /// Note that a return value of `false` does not guarantee the channel will
+    /// remain connected. The channel may be disconnected immediately after this method
+    /// returns, so a subsequent [`Receiver::recv`] may still fail with [`RecvError`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(mpmc_channel)]
+    ///
+    /// use std::sync::mpmc::channel;
+    ///
+    /// let (tx, rx) = channel::<i32>();
+    /// assert!(!rx.is_disconnected());
+    /// drop(tx);
+    /// assert!(rx.is_disconnected());
+    /// ```
+    #[unstable(feature = "mpmc_channel", issue = "126840")]
+    pub fn is_disconnected(&self) -> bool {
+        match &self.flavor {
+            ReceiverFlavor::Array(chan) => chan.is_disconnected(),
+            ReceiverFlavor::List(chan) => chan.is_disconnected(),
+            ReceiverFlavor::Zero(chan) => chan.is_disconnected(),
+        }
+    }
 }
 
 #[unstable(feature = "mpmc_channel", issue = "126840")]

filename: library/std/src/sync/mpmc/zero.rs
patch: @@ -316,4 +316,10 @@ impl<T> Channel<T> {
     pub(crate) fn is_full(&self) -> bool {
         true
     }
+
+    /// Returns `true` if the channel is disconnected.
+    pub(crate) fn is_disconnected(&self) -> bool {
+        let inner = self.inner.lock().unwrap();
+        inner.is_disconnected
+    }
 }

filename: library/std/src/sync/mpsc.rs
patch: @@ -607,6 +607,29 @@ impl<T> Sender<T> {
     pub fn send(&self, t: T) -> Result<(), SendError<T>> {
         self.inner.send(t)
     }
+
+    /// Returns `true` if the channel is disconnected.
+    ///
+    /// Note that a return value of `false` does not guarantee the channel will
+    /// remain connected. The channel may be disconnected immediately after this method
+    /// returns, so a subsequent [`Sender::send`] may still fail with [`SendError`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(mpsc_is_disconnected)]
+    ///
+    /// use std::sync::mpsc::channel;
+    ///
+    /// let (tx, rx) = channel::<i32>();
+    /// assert!(!tx.is_disconnected());
+    /// drop(rx);
+    /// assert!(tx.is_disconnected());
+    /// ```
+    #[unstable(feature = "mpsc_is_disconnected", issue = "153668")]
+    pub fn is_disconnected(&self) -> bool {
+        self.inner.is_disconnected()
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1038,6 +1061,29 @@ impl<T> Receiver<T> {
     pub fn try_iter(&self) -> TryIter<'_, T> {
         TryIter { rx: self }
     }
+
+    /// Returns `true` if the channel is disconnected.
+    ///
+    /// Note that a return value of `false` does not guarantee the channel will
+    /// remain connected. The channel may be disconnected immediately after this method
+    /// returns, so a subsequent [`Receiver::recv`] may still fail with [`RecvError`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(mpsc_is_disconnected)]
+    ///
+    /// use std::sync::mpsc::channel;
+    ///
+    /// let (tx, rx) = channel::<i32>();
+    /// assert!(!rx.is_disconnected());
+    /// drop(tx);
+    /// assert!(rx.is_disconnected());
+    /// ```
+    #[unstable(feature = "mpsc_is_disconnected", issue = "153668")]
+    pub fn is_disconnected(&self) -> bool {
+        self.inner.is_disconnected()
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]