diff --git a/tokio/src/sync/oneshot.rs b/tokio/src/sync/oneshot.rs index d5fc811da2a..8ee0ef702d4 100644 --- a/tokio/src/sync/oneshot.rs +++ b/tokio/src/sync/oneshot.rs @@ -229,6 +229,14 @@ pub struct Sender { /// This channel has no `recv` method because the receiver itself implements the /// [`Future`] trait. To receive a value, `.await` the `Receiver` object directly. /// +/// The `poll` method on the `Future` trait is allowed to spuriously return +/// `Poll::Pending` even if the message has been sent. If such a spurious +/// failure happens, then the caller will be woken when the spurious failure has +/// been resolved so that the caller can attempt to receive the message again. +/// Note that receiving such a wakeup does not guarantee that the next call will +/// succeed — it could fail with another spurious failure. (A spurious failure +/// does not mean that the message is lost. It is just delayed.) +/// /// [`Future`]: trait@std::future::Future /// /// # Examples @@ -923,12 +931,16 @@ impl Receiver { /// This function is useful to call from outside the context of an /// asynchronous task. /// + /// Note that unlike the `poll` method, the `try_recv` method cannot fail + /// spuriously. Any send or close event that happens before this call to + /// `try_recv` will be correctly returned to the caller. + /// /// # Return /// /// - `Ok(T)` if a value is pending in the channel. /// - `Err(TryRecvError::Empty)` if no value has been sent yet. /// - `Err(TryRecvError::Closed)` if the sender has dropped without sending - /// a value. + /// a value, or if the message has already been received. /// /// # Examples /// diff --git a/tokio/tests/sync_oneshot.rs b/tokio/tests/sync_oneshot.rs index 44d09e8adeb..7714f80be93 100644 --- a/tokio/tests/sync_oneshot.rs +++ b/tokio/tests/sync_oneshot.rs @@ -212,6 +212,18 @@ fn try_recv_after_completion() { rx.close(); } +#[test] +fn try_recv_after_completion_await() { + let (tx, rx) = oneshot::channel::(); + let mut rx = task::spawn(rx); + + tx.send(17).unwrap(); + + assert_eq!(Ok(17), assert_ready!(rx.poll())); + assert_eq!(Err(TryRecvError::Closed), rx.try_recv()); + rx.close(); +} + #[test] fn drops_tasks() { let (mut tx, mut rx) = oneshot::channel::();