1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
use super::{dealloc, Channel};
use core::fmt;
use core::mem;
use core::ptr::NonNull;
/// An error returned when trying to send on a closed channel. Returned from
/// [`Sender::send`](crate::Sender::send) if the corresponding [`Receiver`](crate::Receiver)
/// has already been dropped.
///
/// The message that could not be sent can be retreived again with [`SendError::into_inner`].
pub struct SendError<T> {
channel_ptr: NonNull<Channel<T>>,
}
unsafe impl<T: Send> Send for SendError<T> {}
unsafe impl<T: Sync> Sync for SendError<T> {}
impl<T> SendError<T> {
/// # Safety
///
/// By calling this function, the caller semantically transfers ownership of the
/// channel's resources to the created `SendError`. Thus the caller must ensure that the
/// pointer is not used in a way which would violate this ownership transfer. Moreover,
/// the caller must assert that the channel contains a valid, initialized message.
pub(crate) const unsafe fn new(channel_ptr: NonNull<Channel<T>>) -> Self {
Self { channel_ptr }
}
/// Consumes the error and returns the message that failed to be sent.
#[inline]
pub fn into_inner(self) -> T {
let channel_ptr = self.channel_ptr;
// Don't run destructor if we consumed ourselves. Freeing happens here.
mem::forget(self);
// SAFETY: we have ownership of the channel
let channel: &Channel<T> = unsafe { channel_ptr.as_ref() };
// SAFETY: we know that the message is initialized according to the safety requirements of
// `new`
let message = unsafe { channel.take_message() };
// SAFETY: we own the channel
unsafe { dealloc(channel_ptr) };
message
}
/// Get a reference to the message that failed to be sent.
#[inline]
pub fn as_inner(&self) -> &T {
unsafe { self.channel_ptr.as_ref().message().assume_init_ref() }
}
}
impl<T> Drop for SendError<T> {
fn drop(&mut self) {
// SAFETY: we have ownership of the channel and require that the message is initialized
// upon construction
unsafe {
self.channel_ptr.as_ref().drop_message();
dealloc(self.channel_ptr);
}
}
}
impl<T> fmt::Display for SendError<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
"sending on a closed channel".fmt(f)
}
}
impl<T> fmt::Debug for SendError<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "SendError<{}>(_)", stringify!(T))
}
}
#[cfg(feature = "std")]
impl<T> std::error::Error for SendError<T> {}
/// An error returned from receiving methods that block/wait until a message is available.
///
/// The receive operation can only fail if the corresponding [`Sender`](crate::Sender) was dropped
/// before sending any message, or if a message has already been received on the channel.
#[cfg(any(feature = "std", feature = "async"))]
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub struct RecvError;
#[cfg(any(feature = "std", feature = "async"))]
impl fmt::Display for RecvError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
"receiving on a closed channel".fmt(f)
}
}
#[cfg(feature = "std")]
impl std::error::Error for RecvError {}
/// An error returned when failing to receive a message in the non-blocking
/// [`Receiver::try_recv`](crate::Receiver::try_recv).
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum TryRecvError {
/// The channel is still open, but there was no message present in it.
Empty,
/// The channel is closed. Either the sender was dropped before sending any message, or the
/// message has already been extracted from the receiver.
Disconnected,
}
impl fmt::Display for TryRecvError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let msg = match self {
TryRecvError::Empty => "receiving on an empty channel",
TryRecvError::Disconnected => "receiving on a closed channel",
};
msg.fmt(f)
}
}
#[cfg(feature = "std")]
impl std::error::Error for TryRecvError {}
/// An error returned when failing to receive a message in a method that block/wait for a message
/// for a while, but has a timeout after which it gives up.
#[cfg(feature = "std")]
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum RecvTimeoutError {
/// No message arrived on the channel before the timeout was reached. The channel is still open.
Timeout,
/// The channel is closed. Either the sender was dropped before sending any message, or the
/// message has already been extracted from the receiver.
Disconnected,
}
#[cfg(feature = "std")]
impl fmt::Display for RecvTimeoutError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let msg = match self {
RecvTimeoutError::Timeout => "timed out waiting on channel",
RecvTimeoutError::Disconnected => "channel is empty and sending half is closed",
};
msg.fmt(f)
}
}
#[cfg(feature = "std")]
impl std::error::Error for RecvTimeoutError {}