| 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 the blocking [`Receiver::recv`](crate::Receiver::recv) method. |
| /// |
| /// 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 sent and received on the channel. |
| #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] |
| pub struct RecvError; |
| |
| 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 |
| /// [`Receiver::recv_timeout`](crate::Receiver::recv_timeout). |
| #[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, |
| } |
| |
| 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 {} |