about summary refs log tree commit diff
path: root/src/libstd/sync
diff options
context:
space:
mode:
authorJulien Cretin <cretin@google.com>2017-11-12 00:30:46 +0100
committeria0 <git@ia0.eu>2017-11-13 22:50:22 +0100
commit428c875ac33c1a8375d4e583ea708e230a324310 (patch)
tree2b66b0a90b237129e9ee4ddcfd8e146ff5418447 /src/libstd/sync
parent24bb4d1e758423dd10b517628401c1b2c2437715 (diff)
downloadrust-428c875ac33c1a8375d4e583ea708e230a324310.tar.gz
rust-428c875ac33c1a8375d4e583ea708e230a324310.zip
Add std::sync::mpsc::Receiver::recv_deadline()
Essentially renames recv_max_until to recv_deadline (mostly copying recv_timeout
documentation). This function is useful to avoid the often unnecessary call to
Instant::now in recv_timeout (e.g. when the user already has a deadline). A
concrete example would be something along those lines:

```rust
use std::sync::mpsc::Receiver;
use std::time::{Duration, Instant};

/// Reads a batch of elements
///
/// Returns as soon as `max_size` elements have been received or `timeout` expires.
fn recv_batch_timeout<T>(receiver: &Receiver<T>, timeout: Duration, max_size: usize) -> Vec<T> {
    recv_batch_deadline(receiver, Instant::now() + timeout, max_size)
}

/// Reads a batch of elements
///
/// Returns as soon as `max_size` elements have been received or `deadline` is reached.
fn recv_batch_deadline<T>(receiver: &Receiver<T>, deadline: Instant, max_size: usize) -> Vec<T> {
    let mut result = Vec::new();
    while let Ok(x) = receiver.recv_deadline(deadline) {
        result.push(x);
        if result.len() == max_size {
            break;
        }
    }
    result
}
```
Diffstat (limited to 'src/libstd/sync')
-rw-r--r--src/libstd/sync/mpsc/mod.rs63
1 files changed, 61 insertions, 2 deletions
diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs
index 45a26e594b0..6462c1b7976 100644
--- a/src/libstd/sync/mpsc/mod.rs
+++ b/src/libstd/sync/mpsc/mod.rs
@@ -1297,11 +1297,70 @@ impl<T> Receiver<T> {
             Err(TryRecvError::Disconnected)
                 => Err(RecvTimeoutError::Disconnected),
             Err(TryRecvError::Empty)
-                => self.recv_max_until(Instant::now() + timeout)
+                => self.recv_deadline(Instant::now() + timeout)
         }
     }
 
-    fn recv_max_until(&self, deadline: Instant) -> Result<T, RecvTimeoutError> {
+    /// Attempts to wait for a value on this receiver, returning an error if the
+    /// corresponding channel has hung up, or if `deadline` is reached.
+    ///
+    /// 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.
+    ///
+    /// If the corresponding [`Sender`] has disconnected, or it disconnects while
+    /// this call is blocking, this call will wake up and return [`Err`] to
+    /// indicate that no more messages can ever be received on this channel.
+    /// However, since channels are buffered, messages sent before the disconnect
+    /// will still be properly received.
+    ///
+    /// [`Sender`]: struct.Sender.html
+    /// [`SyncSender`]: struct.SyncSender.html
+    /// [`Err`]: ../../../std/result/enum.Result.html#variant.Err
+    ///
+    /// # Examples
+    ///
+    /// Successfully receiving value before reaching deadline:
+    ///
+    /// ```no_run
+    /// use std::thread;
+    /// use std::time::{Duration, Instant};
+    /// use std::sync::mpsc;
+    ///
+    /// let (send, recv) = mpsc::channel();
+    ///
+    /// thread::spawn(move || {
+    ///     send.send('a').unwrap();
+    /// });
+    ///
+    /// assert_eq!(
+    ///     recv.recv_deadline(Instant::now() + Duration::from_millis(400)),
+    ///     Ok('a')
+    /// );
+    /// ```
+    ///
+    /// Receiving an error upon reaching deadline:
+    ///
+    /// ```no_run
+    /// use std::thread;
+    /// use std::time::{Duration, Instant};
+    /// use std::sync::mpsc;
+    ///
+    /// let (send, recv) = mpsc::channel();
+    ///
+    /// thread::spawn(move || {
+    ///     thread::sleep(Duration::from_millis(800));
+    ///     send.send('a').unwrap();
+    /// });
+    ///
+    /// assert_eq!(
+    ///     recv.recv_deadline(Instant::now() + Duration::from_millis(400)),
+    ///     Err(mpsc::RecvTimeoutError::Timeout)
+    /// );
+    /// ```
+    #[stable(feature = "mpsc_recv_deadline", since = "1.23.0")]
+    pub fn recv_deadline(&self, deadline: Instant) -> Result<T, RecvTimeoutError> {
         use self::RecvTimeoutError::*;
 
         loop {