Repository: tokio-rs/tokio
File: tokio/src/sync/mpsc/bounded.rs (Rust)

Code before:
    ///     assert!(permit.next().is_none());
    ///
    ///     // The value sent on the permit is received
    ///     assert_eq!(rx.recv().await.unwrap(), 456);
    ///     assert_eq!(rx.recv().await.unwrap(), 457);
    ///     
    ///     // Trying to call try_reserve_many with 0 will return an empty iterator
    ///     let mut permit = tx.try_reserve_many(0).unwrap();
    ///     assert!(permit.next().is_none());
    ///
    ///     // Trying to call try_reserve_many with a number greater than the channel
    ///     // capacity will return an error
    ///     let permit = tx.try_reserve_many(3);
    ///     assert!(permit.is_err());
    /// }
    /// ```
    pub fn try_reserve_many(&self, n: usize) -> Result<PermitIterator<'_, T>, TrySendError<()>> {
        if n > self.max_capacity() {
            return Err(TrySendError::Full(()));
        }
        if n == 0 {
            return Ok(PermitIterator {
                chan: &self.chan,
                n,
            });
        }

        match self.chan.semaphore().semaphore.try_acquire(n) {
            Ok(()) => {}
            Err(TryAcquireError::Closed) => return Err(TrySendError::Closed(())),
            Err(TryAcquireError::NoPermits) => return Err(TrySendError::Full(())),
        }

        Ok(PermitIterator {
            chan: &self.chan,
            n,
        })
    }

    /// Tries to acquire a slot in the channel without waiting for the slot to become
    /// available, returning an owned permit.
    ///
    /// This moves the sender _by value_, and returns an owned permit that can
    /// be used to send a message into the channel. Unlike [`Sender::try_reserve`],
    /// this method may be used in cases where the permit must be valid for the
    /// `'static` lifetime.  `Sender`s may be cloned cheaply (`Sender::clone` is
    /// essentially a reference count increment, comparable to [`Arc::clone`]),
    /// so when multiple [`OwnedPermit`]s are needed or the `Sender` cannot be
    /// moved, it can be cloned prior to calling `try_reserve_owned`.
    ///
    /// If the channel is full this function will return a [`TrySendError`].

Review comment (suggestion):
Hmm. This means that we don't return closed errors for `n == 0`. Perhaps we should include an "is the channel closed?" test here?

And include a test for this particular case please.

Code after:
    /// [`Permit`]: Permit
    /// [`send`]: Permit::send
    /// [`reserve`]: Sender::reserve
    ///
    /// # Examples
    ///
    /// ```
    /// use tokio::sync::mpsc;
    ///
    /// #[tokio::main]
    /// async fn main() {
    ///     let (tx, mut rx) = mpsc::channel(1);
    ///
    ///     // Reserve capacity
    ///     let permit = tx.try_reserve().unwrap();
    ///
    ///     // Trying to send directly on the `tx` will fail due to no
    ///     // available capacity.
    ///     assert!(tx.try_send(123).is_err());
    ///
    ///     // Trying to reserve an additional slot on the `tx` will
    ///     // fail because there is no capacity.
    ///     assert!(tx.try_reserve().is_err());
    ///
    ///     // Sending on the permit succeeds
    ///     permit.send(456);
    ///
    ///     // The value sent on the permit is received
    ///     assert_eq!(rx.recv().await.unwrap(), 456);
    ///
    /// }
    /// ```
    pub fn try_reserve(&self) -> Result<Permit<'_, T>, TrySendError<()>> {
        match self.chan.semaphore().semaphore.try_acquire(1) {
            Ok(()) => {}
            Err(TryAcquireError::Closed) => return Err(TrySendError::Closed(())),
            Err(TryAcquireError::NoPermits) => return Err(TrySendError::Full(())),
        }

        Ok(Permit { chan: &self.chan })
    }

    /// Tries to acquire `n` slots in the channel without waiting for the slot to become
    /// available.
    ///
    /// A [`PermitIterator`] is returned to track the reserved capacity.
    /// You can call this [`Iterator`] until it is exhausted to
    /// get a [`Permit`] and then call [`Permit::send`]. This function is similar to
    /// [`reserve_many`] except it does not await for the slots to become available.
    ///
    /// If there are fewer than `n` permits available on the channel, then