| 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 {} |