diff --git a/src/lib.rs b/src/lib.rs index e3b2eee..f702ef2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -432,7 +432,11 @@ impl Core { return match head_idx.cmp(&tail_idx) { cmp::Ordering::Less => tail_idx - head_idx, cmp::Ordering::Greater => self.capacity - head_idx + tail_idx, - _ if tail == head => 0, + // Ignore the closed bit when comparing head and tail here, + // since it's not relevant to the length of the channel. If + // both indices point at the same slot and lap, the length + // is zero, even if the channel has been closed. + _ if (tail & !self.closed) == (head & !self.closed) => 0, _ => self.capacity, }; } @@ -665,3 +669,31 @@ impl fmt::Display for Full { #[cfg(feature = "std")] impl std::error::Error for Full {} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn zero_len() { + const CAP: usize = 16; + let mut core = Core::new(CAP); + assert_eq!(core.len(), 0); + assert_eq!(core.capacity(), CAP); + + // don't panic in drop impl. + core.has_dropped_slots = true; + } + + #[test] + fn closed_channel_len() { + const CAP: usize = 16; + let mut core = Core::new(CAP); + core.close(); + assert_eq!(core.len(), 0); + assert_eq!(core.capacity(), CAP); + + // don't panic in drop impl. + core.has_dropped_slots = true; + } +} diff --git a/src/mpsc/async_impl.rs b/src/mpsc/async_impl.rs index 5d424f9..9f410d2 100644 --- a/src/mpsc/async_impl.rs +++ b/src/mpsc/async_impl.rs @@ -263,6 +263,119 @@ feature! { .core .try_send(self.inner.slots.as_ref(), val, &self.inner.recycle) } + + /// Returns the *total* capacity of the channel for this [`Sender`]. + /// This includes both occupied and unoccupied entries. + /// + /// To determine the channel's remaining *unoccupied* capacity, use + /// [`remaining`] instead. + /// + /// # Examples + /// + /// ``` + /// use thingbuf::mpsc::channel; + /// + /// let (tx, _) = channel::(100); + /// assert_eq!(tx.capacity(), 100); + /// ``` + /// + /// Even after sending several messages, the capacity remains + /// the same: + /// ``` + /// # use thingbuf::mpsc::channel; + /// + /// let (tx, rx) = channel::(100); + /// *tx.try_send_ref().unwrap() = 1; + /// *tx.try_send_ref().unwrap() = 2; + /// *tx.try_send_ref().unwrap() = 3; + /// + /// assert_eq!(tx.capacity(), 100); + /// ``` + /// + /// [`remaining`]: Self::remaining + #[inline] + #[must_use] + pub fn capacity(&self) -> usize { + self.inner.core.core.capacity() + } + + /// Returns the unoccupied capacity of the channel for this [`Sender`] + /// (i.e., how many additional elements can be sent before the channel + /// will be full). + /// + /// This is equivalent to subtracting the channel's [`len`] from its [`capacity`]. + /// + /// # Examples + /// + /// ``` + /// use thingbuf::mpsc::channel; + /// + /// let (tx, rx) = channel::(100); + /// assert_eq!(tx.remaining(), 100); + /// + /// *tx.try_send_ref().unwrap() = 1; + /// *tx.try_send_ref().unwrap() = 2; + /// *tx.try_send_ref().unwrap() = 3; + /// assert_eq!(tx.remaining(), 97); + /// + /// let _ = rx.try_recv_ref().unwrap(); + /// assert_eq!(tx.remaining(), 98) + /// ``` + /// + /// [`len`]: Self::len + /// [`capacity`]: Self::capacity + #[must_use] + pub fn remaining(&self) -> usize { + self.capacity() - self.len() + } + + /// Returns the number of elements in the channel of this [`Sender`]. + /// + /// To determine the channel's remaining *unoccupied* capacity, use + /// [`remaining`] instead. + /// + /// # Examples + /// + /// ``` + /// use thingbuf::mpsc::channel; + /// + /// let (tx, rx) = channel::(100); + /// assert_eq!(tx.len(), 0); + /// + /// *tx.try_send_ref().unwrap() = 1; + /// *tx.try_send_ref().unwrap() = 2; + /// *tx.try_send_ref().unwrap() = 3; + /// assert_eq!(tx.len(), 3); + /// + /// let _ = rx.try_recv_ref().unwrap(); + /// assert_eq!(tx.len(), 2); + /// ``` + /// + /// [`remaining`]: Self::remaining + #[inline] + #[must_use] + pub fn len(&self) -> usize { + self.inner.core.core.len() + } + + /// Returns whether the number of elements in the channel of this [`Sender`] is 0. + /// + /// # Examples + /// ``` + /// use thingbuf::mpsc::channel; + /// let (tx, rx) = channel::(100); + /// assert!(tx.is_empty()); + /// + /// *tx.try_send_ref().unwrap() = 1; + /// + /// assert!(!tx.is_empty()); + /// ``` + /// + #[inline] + #[must_use] + pub fn is_empty(&self) -> bool { + self.len() == 0 + } } impl Clone for Sender { @@ -587,6 +700,118 @@ feature! { pub fn is_closed(&self) -> bool { test_dbg!(self.inner.core.tx_count.load(Ordering::SeqCst)) <= 1 } + + /// Returns the *total* capacity of the channel for this [`Receiver`]. + /// This includes both occupied and unoccupied entries. + /// + /// To determine the channel's remaining *unoccupied* capacity, use + /// [`remaining`] instead. + /// + /// # Examples + /// + /// ``` + /// use thingbuf::mpsc::channel; + /// + /// let (tx, rx) = channel::(100); + /// assert_eq!(rx.capacity(), 100); + /// ``` + /// + /// Even after sending several messages, the capacity remains + /// the same: + /// ``` + /// # use thingbuf::mpsc::channel; + /// + /// let (tx, rx) = channel::(100); + /// *tx.try_send_ref().unwrap() = 1; + /// *tx.try_send_ref().unwrap() = 2; + /// *tx.try_send_ref().unwrap() = 3; + /// + /// assert_eq!(rx.capacity(), 100); + /// ``` + /// + /// [`remaining`]: Self::remaining + #[inline] + #[must_use] + pub fn capacity(&self) -> usize { + self.inner.core.core.capacity() + } + + /// Returns the unoccupied capacity of the channel for this [`Receiver`] + /// (i.e., how many additional elements can be sent before the channel + /// will be full). + /// + /// This is equivalent to subtracting the channel's [`len`] from its [`capacity`]. + /// # Examples + /// + /// ``` + /// use thingbuf::mpsc::channel; + /// + /// let (tx, rx) = channel::(100); + /// assert_eq!(rx.remaining(), 100); + /// + /// *tx.try_send_ref().unwrap() = 1; + /// *tx.try_send_ref().unwrap() = 2; + /// *tx.try_send_ref().unwrap() = 3; + /// assert_eq!(rx.remaining(), 97); + /// + /// let _ = rx.try_recv_ref().unwrap(); + /// assert_eq!(rx.remaining(), 98) + /// ``` + /// + /// [`len`]: Self::len + /// [`capacity`]: Self::capacity + #[must_use] + pub fn remaining(&self) -> usize { + self.capacity() - self.len() + } + + /// Returns the number of elements in the channel of this [`Receiver`]. + /// + /// To determine the channel's remaining *unoccupied* capacity, use + /// [`remaining`] instead. + /// + /// # Examples + /// + /// ``` + /// use thingbuf::mpsc::channel; + /// + /// let (tx, rx) = channel::(100); + /// assert_eq!(rx.len(), 0); + /// + /// *tx.try_send_ref().unwrap() = 1; + /// *tx.try_send_ref().unwrap() = 2; + /// *tx.try_send_ref().unwrap() = 3; + /// assert_eq!(rx.len(), 3); + /// + /// let _ = rx.try_recv_ref().unwrap(); + /// assert_eq!(rx.len(), 2); + /// ``` + /// + /// [`remaining`]: Self::remaining + #[inline] + #[must_use] + pub fn len(&self) -> usize { + self.inner.core.core.len() + } + + /// Returns whether the number of elements in the channel of this [`Receiver`] is 0. + /// + /// # Examples + /// ``` + /// use thingbuf::mpsc::channel; + /// let (tx, rx) = channel::(100); + /// assert!(rx.is_empty()); + /// + /// *tx.try_send_ref().unwrap() = 1; + /// + /// assert!(!rx.is_empty()); + /// ``` + /// + #[inline] + #[must_use] + pub fn is_empty(&self) -> bool { + self.len() == 0 + } } impl Drop for Receiver { @@ -948,6 +1173,130 @@ feature! { pub fn try_send(&self, val: T) -> Result<(), TrySendError> { self.core.try_send(self.slots, val, self.recycle) } + + /// Returns the *total* capacity of the channel for this [`StaticSender`]. + /// This includes both occupied and unoccupied entries. + /// + /// To determine the channel's remaining *unoccupied* capacity, use + /// [`remaining`] instead. + /// + /// # Examples + /// + /// ``` + /// use thingbuf::mpsc::StaticChannel; + /// + /// static CHANNEL: StaticChannel = StaticChannel::new(); + /// + /// let (tx, _) = CHANNEL.split(); + /// assert_eq!(tx.capacity(), 100); + /// ``` + /// + /// Even after sending several messages, the capacity remains + /// the same: + /// ``` + /// # use thingbuf::mpsc::StaticChannel; + /// + /// # static CHANNEL: StaticChannel = StaticChannel::new(); + /// + /// let (tx, rx) = CHANNEL.split(); + /// *tx.try_send_ref().unwrap() = 1; + /// *tx.try_send_ref().unwrap() = 2; + /// *tx.try_send_ref().unwrap() = 3; + /// + /// assert_eq!(tx.capacity(), 100); + /// ``` + /// + /// [`remaining`]: Self::remaining + #[inline] + #[must_use] + pub fn capacity(&self) -> usize { + self.core.core.capacity() + } + + /// Returns the unoccupied capacity of the channel for this [`StaticSender`] + /// (i.e., how many additional elements can be sent before the channel + /// will be full). + /// + /// This is equivalent to subtracting the channel's [`len`] from its [`capacity`]. + /// + /// # Examples + /// + /// ``` + /// use thingbuf::mpsc::StaticChannel; + /// + /// static CHANNEL: StaticChannel = StaticChannel::new(); + /// + /// let (tx, rx) = CHANNEL.split(); + /// assert_eq!(tx.remaining(), 100); + /// + /// *tx.try_send_ref().unwrap() = 1; + /// *tx.try_send_ref().unwrap() = 2; + /// *tx.try_send_ref().unwrap() = 3; + /// assert_eq!(tx.remaining(), 97); + /// + /// let _ = rx.try_recv_ref().unwrap(); + /// assert_eq!(tx.remaining(), 98) + /// ``` + /// + /// [`len`]: Self::len + /// [`capacity`]: Self::capacity + #[must_use] + pub fn remaining(&self) -> usize { + self.capacity() - self.len() + } + + /// Returns the number of elements in the channel of this [`StaticSender`]. + /// + /// To determine the channel's remaining *unoccupied* capacity, use + /// [`remaining`] instead. + /// + /// # Examples + /// + /// ``` + /// use thingbuf::mpsc::StaticChannel; + /// + /// static CHANNEL: StaticChannel = StaticChannel::new(); + /// + /// let (tx, rx) = CHANNEL.split(); + /// assert_eq!(tx.len(), 0); + /// + /// *tx.try_send_ref().unwrap() = 1; + /// *tx.try_send_ref().unwrap() = 2; + /// *tx.try_send_ref().unwrap() = 3; + /// assert_eq!(tx.len(), 3); + /// + /// let _ = rx.try_recv_ref().unwrap(); + /// assert_eq!(tx.len(), 2); + /// ``` + /// + /// [`remaining`]: Self::remaining + #[inline] + #[must_use] + pub fn len(&self) -> usize { + self.core.core.len() + } + + /// Returns whether the number of elements in the channel of this [`StaticSender`] is 0. + /// + /// # Examples + /// ``` + /// use thingbuf::mpsc::StaticChannel; + /// + /// static CHANNEL: StaticChannel = StaticChannel::new(); + /// + /// let (tx, rx) = CHANNEL.split(); + /// assert!(tx.is_empty()); + /// + /// *tx.try_send_ref().unwrap() = 1; + /// + /// assert!(!tx.is_empty()); + /// ``` + /// + #[inline] + #[must_use] + pub fn is_empty(&self) -> bool { + self.len() == 0 + } } impl Clone for StaticSender { @@ -1292,6 +1641,129 @@ feature! { pub fn is_closed(&self) -> bool { test_dbg!(self.core.tx_count.load(Ordering::SeqCst)) <= 1 } + + /// Returns the *total* capacity of the channel for this [`StaticReceiver`]. + /// This includes both occupied and unoccupied entries. + /// + /// To determine the channel's remaining *unoccupied* capacity, use + /// [`remaining`] instead. + /// + /// # Examples + /// + /// ``` + /// use thingbuf::mpsc::StaticChannel; + /// + /// static CHANNEL: StaticChannel = StaticChannel::new(); + /// + /// let (_, rx) = CHANNEL.split(); + /// assert_eq!(rx.capacity(), 100); + /// ``` + /// + /// Even after sending several messages, the capacity remains + /// the same: + /// ``` + /// # use thingbuf::mpsc::StaticChannel; + /// + /// # static CHANNEL: StaticChannel = StaticChannel::new(); + /// + /// let (tx, rx) = CHANNEL.split(); + /// *tx.try_send_ref().unwrap() = 1; + /// *tx.try_send_ref().unwrap() = 2; + /// *tx.try_send_ref().unwrap() = 3; + /// + /// assert_eq!(rx.capacity(), 100); + /// ``` + /// + /// [`remaining`]: Self::remaining + #[inline] + #[must_use] + pub fn capacity(&self) -> usize { + self.core.core.capacity() + } + + /// Returns the unoccupied capacity of the channel for this [`StaticReceiver`] + /// (i.e., how many additional elements can be sent before the channel + /// will be full). + /// + /// This is equivalent to subtracting the channel's [`len`] from its [`capacity`]. + /// # Examples + /// + /// ``` + /// use thingbuf::mpsc::StaticChannel; + /// + /// static CHANNEL: StaticChannel = StaticChannel::new(); + /// + /// let (tx, rx) = CHANNEL.split(); + /// assert_eq!(rx.remaining(), 100); + /// + /// *tx.try_send_ref().unwrap() = 1; + /// *tx.try_send_ref().unwrap() = 2; + /// *tx.try_send_ref().unwrap() = 3; + /// assert_eq!(rx.remaining(), 97); + /// + /// let _ = rx.try_recv_ref().unwrap(); + /// assert_eq!(rx.remaining(), 98) + /// ``` + /// + /// [`len`]: Self::len + /// [`capacity`]: Self::capacity + #[must_use] + pub fn remaining(&self) -> usize { + self.capacity() - self.len() + } + + /// Returns the number of elements in the channel of this [`StaticReceiver`]. + /// + /// To determine the channel's remaining *unoccupied* capacity, use + /// [`remaining`] instead. + /// + /// # Examples + /// + /// ``` + /// use thingbuf::mpsc::StaticChannel; + /// + /// static CHANNEL: StaticChannel = StaticChannel::new(); + /// + /// let (tx, rx) = CHANNEL.split(); + /// assert_eq!(rx.len(), 0); + /// + /// *tx.try_send_ref().unwrap() = 1; + /// *tx.try_send_ref().unwrap() = 2; + /// *tx.try_send_ref().unwrap() = 3; + /// assert_eq!(rx.len(), 3); + /// + /// let _ = rx.try_recv_ref().unwrap(); + /// assert_eq!(rx.len(), 2); + /// ``` + /// + /// [`remaining`]: Self::remaining + #[inline] + #[must_use] + pub fn len(&self) -> usize { + self.core.core.len() + } + + /// Returns whether the number of elements in the channel of this [`StaticReceiver`] is 0. + /// + /// # Examples + /// ``` + /// use thingbuf::mpsc::StaticChannel; + /// + /// static CHANNEL: StaticChannel = StaticChannel::new(); + /// + /// let (tx, rx) = CHANNEL.split(); + /// assert!(rx.is_empty()); + /// + /// *tx.try_send_ref().unwrap() = 1; + /// + /// assert!(!rx.is_empty()); + /// ``` + /// + #[inline] + #[must_use] + pub fn is_empty(&self) -> bool { + self.len() == 0 + } } impl Drop for StaticReceiver { diff --git a/src/mpsc/blocking.rs b/src/mpsc/blocking.rs index 9a85884..49a8aed 100644 --- a/src/mpsc/blocking.rs +++ b/src/mpsc/blocking.rs @@ -4,11 +4,17 @@ //! [`Receiver`] types in this module wait by blocking the current thread, //! rather than asynchronously yielding. use super::*; -use crate::{loom::{ - atomic::{self, Ordering}, - sync::Arc, - thread::{self, Thread}, -}, MAX_CAPACITY, recycling::{self, Recycle}, util::Backoff, wait::queue}; +use crate::{ + loom::{ + atomic::{self, Ordering}, + sync::Arc, + thread::{self, Thread}, + }, + recycling::{self, Recycle}, + util::Backoff, + wait::queue, + MAX_CAPACITY, +}; use core::{fmt, pin::Pin}; use errors::*; use std::time::{Duration, Instant}; @@ -530,6 +536,133 @@ feature! { pub fn try_send(&self, val: T) -> Result<(), TrySendError> { self.core.try_send(self.slots, val, self.recycle) } + + /// Returns the *total* capacity of the channel for this [`StaticSender`]. + /// This includes both occupied and unoccupied entries. + /// + /// To determine the channel's remaining *unoccupied* capacity, use + /// [`remaining`] instead. + /// + /// # Examples + /// + /// ``` + /// use thingbuf::mpsc::blocking::StaticChannel; + /// + /// static CHANNEL: StaticChannel = StaticChannel::new(); + /// + /// let (tx, _) = CHANNEL.split(); + /// assert_eq!(tx.capacity(), 100); + /// ``` + /// + /// Even after sending several messages, the capacity remains + /// the same: + /// ``` + /// # use thingbuf::mpsc::blocking::StaticChannel; + /// + /// # static CHANNEL: StaticChannel = StaticChannel::new(); + /// + /// let (tx, rx) = CHANNEL.split(); + /// *tx.try_send_ref().unwrap() = 1; + /// *tx.try_send_ref().unwrap() = 2; + /// *tx.try_send_ref().unwrap() = 3; + /// + /// assert_eq!(tx.capacity(), 100); + /// ``` + /// + /// [`remaining`]: Self::remaining + #[inline] + #[must_use] + pub fn capacity(&self) -> usize { + self.core.core.capacity() + } + + /// Returns the unoccupied capacity of the channel for this [`StaticSender`] + /// (i.e., how many additional elements can be sent before the channel + /// will be full). + /// + /// This is equivalent to subtracting the channel's [`len`] from its [`capacity`]. + /// + /// # Examples + /// + /// ``` + /// use thingbuf::mpsc::blocking::StaticChannel; + /// + /// static CHANNEL: StaticChannel = StaticChannel::new(); + /// + /// let (tx, rx) = CHANNEL.split(); + /// assert_eq!(tx.remaining(), 100); + /// + /// *tx.try_send_ref().unwrap() = 1; + /// *tx.try_send_ref().unwrap() = 2; + /// *tx.try_send_ref().unwrap() = 3; + /// assert_eq!(tx.remaining(), 97); + /// + /// let _ = rx.try_recv_ref().unwrap(); + /// assert_eq!(tx.remaining(), 98) + /// ``` + /// + /// [`len`]: Self::len + /// [`capacity`]: Self::capacity + #[must_use] + pub fn remaining(&self) -> usize { + self.capacity() - self.len() + } + + /// Returns the number of elements in the channel of this [`StaticSender`]. + /// + /// To determine the channel's remaining *unoccupied* capacity, use + /// [`remaining`] instead. + /// + /// # Examples + /// + /// ``` + /// use thingbuf::mpsc::blocking::StaticChannel; + /// + /// static CHANNEL: StaticChannel = StaticChannel::new(); + /// + /// let (tx, rx) = CHANNEL.split(); + /// assert_eq!(tx.len(), 0); + /// + /// *tx.try_send_ref().unwrap() = 1; + /// *tx.try_send_ref().unwrap() = 2; + /// *tx.try_send_ref().unwrap() = 3; + /// assert_eq!(tx.len(), 3); + /// + /// let _ = rx.try_recv_ref().unwrap(); + /// assert_eq!(tx.len(), 2); + /// ``` + /// + /// [`remaining`]: Self::remaining + #[inline] + #[must_use] + pub fn len(&self) -> usize { + self.core.core.len() + } + + /// Returns whether the number of elements in the channel of this [`StaticSender`] is 0. + /// + /// # Examples + /// ``` + /// use thingbuf::mpsc::blocking::StaticChannel; + /// + /// static CHANNEL: StaticChannel = StaticChannel::new(); + /// + /// let (tx, rx) = CHANNEL.split(); + /// assert!(tx.is_empty()); + /// + /// *tx.try_send_ref().unwrap() = 1; + /// + /// assert!(!tx.is_empty()); + /// # // keep rx alive so that the send call succeeds --- otherwise, + /// # // the channel will close and the send will fail. + /// # drop(rx); + /// ``` + /// + #[inline] + #[must_use] + pub fn is_empty(&self) -> bool { + self.len() == 0 + } } impl Clone for StaticSender { @@ -876,6 +1009,130 @@ feature! { pub fn is_closed(&self) -> bool { test_dbg!(self.core.tx_count.load(Ordering::SeqCst)) <= 1 } + + /// Returns the *total* capacity of the channel for this [`StaticReceiver`]. + /// This includes both occupied and unoccupied entries. + /// + /// To determine the channel's remaining *unoccupied* capacity, use + /// [`remaining`] instead. + /// + /// # Examples + /// + /// ``` + /// use thingbuf::mpsc::blocking::StaticChannel; + /// + /// static CHANNEL: StaticChannel = StaticChannel::new(); + /// + /// let (_, rx) = CHANNEL.split(); + /// assert_eq!(rx.capacity(), 100); + /// ``` + /// + /// Even after sending several messages, the capacity remains + /// the same: + /// ``` + /// # use thingbuf::mpsc::blocking::StaticChannel; + /// + /// # static CHANNEL: StaticChannel = StaticChannel::new(); + /// + /// let (tx, rx) = CHANNEL.split(); + /// *tx.try_send_ref().unwrap() = 1; + /// *tx.try_send_ref().unwrap() = 2; + /// *tx.try_send_ref().unwrap() = 3; + /// + /// assert_eq!(rx.capacity(), 100); + /// ``` + /// + /// [`remaining`]: Self::remaining + #[inline] + #[must_use] + pub fn capacity(&self) -> usize { + self.core.core.capacity() + } + + /// Returns the unoccupied capacity of the channel for this [`StaticReceiver`] + /// (i.e., how many additional elements can be sent before the channel + /// will be full). + /// + /// This is equivalent to subtracting the channel's [`len`] from its [`capacity`]. + /// # Examples + /// + /// ``` + /// use thingbuf::mpsc::blocking::StaticChannel; + /// + /// static CHANNEL: StaticChannel = StaticChannel::new(); + /// + /// let (tx, rx) = CHANNEL.split(); + /// assert_eq!(rx.remaining(), 100); + /// + /// *tx.try_send_ref().unwrap() = 1; + /// *tx.try_send_ref().unwrap() = 2; + /// *tx.try_send_ref().unwrap() = 3; + /// assert_eq!(rx.remaining(), 97); + /// + /// let _ = rx.try_recv_ref().unwrap(); + /// assert_eq!(rx.remaining(), 98) + /// ``` + /// + /// [`len`]: Self::len + /// [`capacity`]: Self::capacity + #[must_use] + pub fn remaining(&self) -> usize { + self.capacity() - self.len() + } + + /// Returns the number of elements in the channel of this [`StaticReceiver`]. + /// + /// To determine the channel's remaining *unoccupied* capacity, use + /// [`remaining`] instead. + /// + /// # Examples + /// + /// ``` + /// use thingbuf::mpsc::blocking::StaticChannel; + /// + /// static CHANNEL: StaticChannel = StaticChannel::new(); + /// + /// let (tx, rx) = CHANNEL.split(); + /// assert_eq!(rx.len(), 0); + /// + /// *tx.try_send_ref().unwrap() = 1; + /// *tx.try_send_ref().unwrap() = 2; + /// *tx.try_send_ref().unwrap() = 3; + /// assert_eq!(rx.len(), 3); + /// + /// let _ = rx.try_recv_ref().unwrap(); + /// assert_eq!(rx.len(), 2); + /// ``` + /// + /// [`remaining`]: Self::remaining + #[inline] + #[must_use] + pub fn len(&self) -> usize { + self.core.core.len() + } + + /// Returns whether the number of elements in the channel of this + /// [`StaticReceiver`] is 0. + /// + /// # Examples + /// ``` + /// use thingbuf::mpsc::blocking::StaticChannel; + /// + /// static CHANNEL: StaticChannel = StaticChannel::new(); + /// + /// let (tx, rx) = CHANNEL.split(); + /// assert!(rx.is_empty()); + /// + /// *tx.try_send_ref().unwrap() = 1; + /// + /// assert!(!rx.is_empty()); + /// ``` + /// + #[inline] + #[must_use] + pub fn is_empty(&self) -> bool { + self.len() == 0 + } } impl<'a, T, R> Iterator for &'a StaticReceiver { @@ -1232,6 +1489,122 @@ where .core .try_send(self.inner.slots.as_ref(), val, &self.inner.recycle) } + + /// Returns the *total* capacity of the channel for this [`Sender`]. + /// This includes both occupied and unoccupied entries. + /// + /// To determine the channel's remaining *unoccupied* capacity, use + /// [`remaining`] instead. + /// + /// # Examples + /// + /// ``` + /// use thingbuf::mpsc::blocking::channel; + /// + /// let (tx, _) = channel::(100); + /// assert_eq!(tx.capacity(), 100); + /// ``` + /// + /// Even after sending several messages, the capacity remains + /// the same: + /// ``` + /// # use thingbuf::mpsc::blocking::channel; + /// + /// let (tx, rx) = channel::(100); + /// *tx.try_send_ref().unwrap() = 1; + /// *tx.try_send_ref().unwrap() = 2; + /// *tx.try_send_ref().unwrap() = 3; + /// + /// assert_eq!(tx.capacity(), 100); + /// ``` + /// + /// [`remaining`]: Self::remaining + #[inline] + #[must_use] + pub fn capacity(&self) -> usize { + self.inner.core.core.capacity() + } + + /// Returns the unoccupied capacity of the channel for this [`Sender`] + /// (i.e., how many additional elements can be sent before the channel + /// will be full). + /// + /// This is equivalent to subtracting the channel's [`len`] from its [`capacity`]. + /// + /// # Examples + /// + /// ``` + /// use thingbuf::mpsc::blocking::channel; + /// + /// let (tx, rx) = channel::(100); + /// assert_eq!(tx.remaining(), 100); + /// + /// *tx.try_send_ref().unwrap() = 1; + /// *tx.try_send_ref().unwrap() = 2; + /// *tx.try_send_ref().unwrap() = 3; + /// assert_eq!(tx.remaining(), 97); + /// + /// let _ = rx.try_recv_ref().unwrap(); + /// assert_eq!(tx.remaining(), 98) + /// ``` + /// + /// [`len`]: Self::len + /// [`capacity`]: Self::capacity + #[must_use] + pub fn remaining(&self) -> usize { + self.capacity() - self.len() + } + + /// Returns the number of elements in the channel of this [`Sender`]. + /// + /// To determine the channel's remaining *unoccupied* capacity, use + /// [`remaining`] instead. + /// + /// # Examples + /// + /// ``` + /// use thingbuf::mpsc::blocking::channel; + /// + /// let (tx, rx) = channel::(100); + /// assert_eq!(tx.len(), 0); + /// + /// *tx.try_send_ref().unwrap() = 1; + /// *tx.try_send_ref().unwrap() = 2; + /// *tx.try_send_ref().unwrap() = 3; + /// assert_eq!(tx.len(), 3); + /// + /// let _ = rx.try_recv_ref().unwrap(); + /// assert_eq!(tx.len(), 2); + /// ``` + /// + /// [`remaining`]: Self::remaining + #[inline] + #[must_use] + pub fn len(&self) -> usize { + self.inner.core.core.len() + } + + /// Returns whether the number of elements in the channel of this [`Sender`] is 0. + /// + /// # Examples + /// ``` + /// use thingbuf::mpsc::blocking::channel; + /// let (tx, rx) = channel::(100); + /// assert!(tx.is_empty()); + /// + /// *tx.try_send_ref().unwrap() = 1; + /// + /// assert!(!tx.is_empty()); + /// # // keep rx alive so that the send call succeeds --- otherwise, + /// # // the channel will close and the send will fail. + /// # drop(rx); + /// ``` + /// + #[inline] + #[must_use] + pub fn is_empty(&self) -> bool { + self.len() == 0 + } } impl Clone for Sender { @@ -1562,6 +1935,118 @@ impl Receiver { pub fn is_closed(&self) -> bool { test_dbg!(self.inner.core.tx_count.load(Ordering::SeqCst)) <= 1 } + + /// Returns the *total* capacity of the channel for this [`Receiver`]. + /// This includes both occupied and unoccupied entries. + /// + /// To determine the channel's remaining *unoccupied* capacity, use + /// [`remaining`] instead. + /// + /// # Examples + /// + /// ``` + /// use thingbuf::mpsc::blocking::channel; + /// + /// let (_, rx) = channel::(100); + /// assert_eq!(rx.capacity(), 100); + /// ``` + /// + /// Even after sending several messages, the capacity remains + /// the same: + /// ``` + /// # use thingbuf::mpsc::blocking::channel; + /// + /// let (tx, rx) = channel::(100); + /// *tx.try_send_ref().unwrap() = 1; + /// *tx.try_send_ref().unwrap() = 2; + /// *tx.try_send_ref().unwrap() = 3; + /// + /// assert_eq!(rx.capacity(), 100); + /// ``` + /// + /// [`remaining`]: Self::remaining + #[inline] + #[must_use] + pub fn capacity(&self) -> usize { + self.inner.core.core.capacity() + } + + /// Returns the unoccupied capacity of the channel for this [`Receiver`] + /// (i.e., how many additional elements can be sent before the channel + /// will be full). + /// + /// This is equivalent to subtracting the channel's [`len`] from its [`capacity`]. + /// # Examples + /// + /// ``` + /// use thingbuf::mpsc::blocking::channel; + /// + /// let (tx, rx) = channel::(100); + /// assert_eq!(rx.remaining(), 100); + /// + /// *tx.try_send_ref().unwrap() = 1; + /// *tx.try_send_ref().unwrap() = 2; + /// *tx.try_send_ref().unwrap() = 3; + /// assert_eq!(rx.remaining(), 97); + /// + /// let _ = rx.try_recv_ref().unwrap(); + /// assert_eq!(rx.remaining(), 98) + /// ``` + /// + /// [`len`]: Self::len + /// [`capacity`]: Self::capacity + #[must_use] + pub fn remaining(&self) -> usize { + self.capacity() - self.len() + } + + /// Returns the number of elements in the channel of this [`Receiver`]. + /// + /// To determine the channel's remaining *unoccupied* capacity, use + /// [`remaining`] instead. + /// + /// # Examples + /// + /// ``` + /// use thingbuf::mpsc::blocking::channel; + /// + /// let (tx, rx) = channel::(100); + /// assert_eq!(rx.len(), 0); + /// + /// *tx.try_send_ref().unwrap() = 1; + /// *tx.try_send_ref().unwrap() = 2; + /// *tx.try_send_ref().unwrap() = 3; + /// assert_eq!(rx.len(), 3); + /// + /// let _ = rx.try_recv_ref().unwrap(); + /// assert_eq!(rx.len(), 2); + /// ``` + /// + /// [`remaining`]: Self::remaining + #[inline] + #[must_use] + pub fn len(&self) -> usize { + self.inner.core.core.len() + } + + /// Returns whether the number of elements in the channel of this [`Receiver`] is 0. + /// + /// # Examples + /// ``` + /// use thingbuf::mpsc::channel; + /// let (tx, rx) = channel::(100); + /// assert!(rx.is_empty()); + /// + /// *tx.try_send_ref().unwrap() = 1; + /// + /// assert!(!rx.is_empty()); + /// ``` + /// + #[inline] + #[must_use] + pub fn is_empty(&self) -> bool { + self.len() == 0 + } } impl<'a, T, R> Iterator for &'a Receiver {