pub struct Receiver<T> { /* private fields */ }
Expand description
Receives a value from the associated Sender
.
A pair of both a Sender
and a Receiver
are created by the
channel
function.
This channel has no recv
method because the receiver itself implements the
Future
trait. To receive a Result<T,
error::RecvError
>
, .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.)
§Examples
use tokio::sync::oneshot;
#[tokio::main]
async fn main() {
let (tx, rx) = oneshot::channel();
tokio::spawn(async move {
if let Err(_) = tx.send(3) {
println!("the receiver dropped");
}
});
match rx.await {
Ok(v) => println!("got = {:?}", v),
Err(_) => println!("the sender dropped"),
}
}
If the sender is dropped without sending, the receiver will fail with
error::RecvError
:
use tokio::sync::oneshot;
#[tokio::main]
async fn main() {
let (tx, rx) = oneshot::channel::<u32>();
tokio::spawn(async move {
drop(tx);
});
match rx.await {
Ok(_) => panic!("This doesn't happen"),
Err(_) => println!("the sender dropped"),
}
}
To use a Receiver
in a tokio::select!
loop, add &mut
in front of the
channel.
use tokio::sync::oneshot;
use tokio::time::{interval, sleep, Duration};
#[tokio::main]
async fn main() {
let (send, mut recv) = oneshot::channel();
let mut interval = interval(Duration::from_millis(100));
tokio::spawn(async move {
sleep(Duration::from_secs(1)).await;
send.send("shut down").unwrap();
});
loop {
tokio::select! {
_ = interval.tick() => println!("Another 100ms"),
msg = &mut recv => {
println!("Got message: {}", msg.unwrap());
break;
}
}
}
}
Implementations§
Source§impl<T> Receiver<T>
impl<T> Receiver<T>
Sourcepub fn close(&mut self)
pub fn close(&mut self)
Prevents the associated Sender
handle from sending a value.
Any send
operation which happens after calling close
is guaranteed
to fail. After calling close
, try_recv
should be called to
receive a value if one was sent before the call to close
completed.
This function is useful to perform a graceful shutdown and ensure that a value will not be sent into the channel and never received.
close
is no-op if a message is already received or the channel
is already closed.
§Examples
Prevent a value from being sent
use tokio::sync::oneshot;
use tokio::sync::oneshot::error::TryRecvError;
#[tokio::main]
async fn main() {
let (tx, mut rx) = oneshot::channel();
assert!(!tx.is_closed());
rx.close();
assert!(tx.is_closed());
assert!(tx.send("never received").is_err());
match rx.try_recv() {
Err(TryRecvError::Closed) => {}
_ => unreachable!(),
}
}
Receive a value sent before calling close
use tokio::sync::oneshot;
#[tokio::main]
async fn main() {
let (tx, mut rx) = oneshot::channel();
assert!(tx.send("will receive").is_ok());
rx.close();
let msg = rx.try_recv().unwrap();
assert_eq!(msg, "will receive");
}
Sourcepub fn is_terminated(&self) -> bool
pub fn is_terminated(&self) -> bool
Checks if this receiver is terminated.
This function returns true if this receiver has already yielded a Poll::Ready
result.
If so, this receiver should no longer be polled.
§Examples
Sending a value and polling it.
use tokio::sync::oneshot;
use std::task::Poll;
#[tokio::main]
async fn main() {
let (tx, mut rx) = oneshot::channel();
// A receiver is not terminated when it is initialized.
assert!(!rx.is_terminated());
// A receiver is not terminated it is polled and is still pending.
let poll = futures::poll!(&mut rx);
assert_eq!(poll, Poll::Pending);
assert!(!rx.is_terminated());
// A receiver is not terminated if a value has been sent, but not yet read.
tx.send(0).unwrap();
assert!(!rx.is_terminated());
// A receiver *is* terminated after it has been polled and yielded a value.
assert_eq!((&mut rx).await, Ok(0));
assert!(rx.is_terminated());
}
Dropping the sender.
use tokio::sync::oneshot;
#[tokio::main]
async fn main() {
let (tx, mut rx) = oneshot::channel::<()>();
// A receiver is not immediately terminated when the sender is dropped.
drop(tx);
assert!(!rx.is_terminated());
// A receiver *is* terminated after it has been polled and yielded an error.
let _ = (&mut rx).await.unwrap_err();
assert!(rx.is_terminated());
}
Sourcepub fn is_empty(&self) -> bool
pub fn is_empty(&self) -> bool
Checks if a channel is empty.
This method returns true
if the channel has no messages.
It is not necessarily safe to poll an empty receiver, which may have
already yielded a value. Use is_terminated()
to check whether or not a receiver can be safely polled, instead.
§Examples
Sending a value.
use tokio::sync::oneshot;
#[tokio::main]
async fn main() {
let (tx, mut rx) = oneshot::channel();
assert!(rx.is_empty());
tx.send(0).unwrap();
assert!(!rx.is_empty());
let _ = (&mut rx).await;
assert!(rx.is_empty());
}
Dropping the sender.
use tokio::sync::oneshot;
#[tokio::main]
async fn main() {
let (tx, mut rx) = oneshot::channel::<()>();
// A channel is empty if the sender is dropped.
drop(tx);
assert!(rx.is_empty());
// A closed channel still yields an error, however.
(&mut rx).await.expect_err("should yield an error");
assert!(rx.is_empty());
}
Terminated channels are empty.
use tokio::sync::oneshot;
#[tokio::main]
async fn main() {
let (tx, mut rx) = oneshot::channel();
tx.send(0).unwrap();
let _ = (&mut rx).await;
// NB: an empty channel is not necessarily safe to poll!
assert!(rx.is_empty());
let _ = (&mut rx).await;
}
Sourcepub fn try_recv(&mut self) -> Result<T, TryRecvError>
pub fn try_recv(&mut self) -> Result<T, TryRecvError>
Attempts to receive a value.
If a pending value exists in the channel, it is returned. If no value has been sent, the current task will not be registered for future notification.
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, or if the message has already been received.
§Examples
try_recv
before a value is sent, then after.
use tokio::sync::oneshot;
use tokio::sync::oneshot::error::TryRecvError;
#[tokio::main]
async fn main() {
let (tx, mut rx) = oneshot::channel();
match rx.try_recv() {
// The channel is currently empty
Err(TryRecvError::Empty) => {}
_ => unreachable!(),
}
// Send a value
tx.send("hello").unwrap();
match rx.try_recv() {
Ok(value) => assert_eq!(value, "hello"),
_ => unreachable!(),
}
}
try_recv
when the sender dropped before sending a value
use tokio::sync::oneshot;
use tokio::sync::oneshot::error::TryRecvError;
#[tokio::main]
async fn main() {
let (tx, mut rx) = oneshot::channel::<()>();
drop(tx);
match rx.try_recv() {
// The channel will never receive a value.
Err(TryRecvError::Closed) => {}
_ => unreachable!(),
}
}
Sourcepub fn blocking_recv(self) -> Result<T, RecvError>
pub fn blocking_recv(self) -> Result<T, RecvError>
Blocking receive to call outside of asynchronous contexts.
§Panics
This function panics if called within an asynchronous execution context.
§Examples
use std::thread;
use tokio::sync::oneshot;
#[tokio::main]
async fn main() {
let (tx, rx) = oneshot::channel::<u8>();
let sync_code = thread::spawn(move || {
assert_eq!(Ok(10), rx.blocking_recv());
});
let _ = tx.send(10);
sync_code.join().unwrap();
}