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

Code before:
    ///
    /// #[tokio::main]
    /// async fn main() {
    ///     let (tx, mut rx) = mpsc::channel(1);
    ///
    ///     // Clone the sender and reserve capacity.
    ///     let permit = tx.clone().reserve_owned().await.unwrap();
    ///
    ///     // Trying to send directly on the `tx` will fail due to no
    ///     // available capacity.
    ///     assert!(tx.try_send(123).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);
    /// }
    /// ```
    ///
    /// [`Sender::reserve`]: Sender::reserve
    /// [`OwnedPermit`]: OwnedPermit
    /// [`send`]: OwnedPermit::send
    /// [`Arc::clone`]: std::sync::Arc::clone
    pub async fn reserve_owned(self) -> Result<OwnedPermit<T>, SendError<()>> {
        self.reserve_inner(1).await?;
        Ok(OwnedPermit {
            chan: Some(self.chan),
        })
    }

    async fn reserve_inner(&self, n: usize) -> Result<(), SendError<()>> {
        crate::trace::async_trace_leaf().await;

        match self.chan.semaphore().semaphore.acquire(n).await {
            Ok(()) => Ok(()),
            Err(_) => Err(SendError(())),
        }
    }

    /// Tries to acquire a slot in the channel without waiting for the slot to become
    /// available.
    ///
    /// If the channel is full this function will return [`TrySendError`], otherwise
    /// if there is a slot available it will return a [`Permit`] that will then allow you
    /// to [`send`] on the channel with a guaranteed slot. This function is similar to
    /// [`reserve`] except it does not await for the slot to become available.
    ///
    /// Dropping [`Permit`] without sending a message releases the capacity back
    /// to the channel.
    ///

Review comment (performance):
I would return a `SendError` if `n > batch_semaphore::MAX_PERMITS` here. I'm not sure how the batch semaphore handles it if you pass something greater than that.

Code after:
    ///     // Reserve capacity
    ///     let mut permit = tx.reserve_many(2).await.unwrap();
    ///
    ///     // Trying to send directly on the `tx` will fail due to no
    ///     // available capacity.
    ///     assert!(tx.try_send(123).is_err());
    ///
    ///     // Sending with the permit iterator succeeds
    ///     permit.next().unwrap().send(456);
    ///     permit.next().unwrap().send(457);
    ///
    ///     // The iterator should now be exhausted
    ///     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);
    /// }
    /// ```
    pub async fn reserve_many(&self, n: usize) -> Result<PermitIterator<'_, T>, SendError<()>> {
        self.reserve_inner(n).await?;
        Ok(PermitIterator {
            chan: &self.chan,
            n,
        })
    }

    /// Waits for channel capacity, moving the `Sender` and returning an owned
    /// permit. Once capacity to send one message is available, it is reserved
    /// for the caller.
    ///
    /// This moves the sender _by value_, and returns an owned permit that can
    /// be used to send a message into the channel. Unlike [`Sender::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 `reserve_owned`.
    ///
    /// If the channel is full, the function waits for the number of unreceived
    /// messages to become less than the channel capacity. Capacity to send one
    /// message is reserved for the caller. An [`OwnedPermit`] is returned to
    /// track the reserved capacity. The [`send`] function on [`OwnedPermit`]
    /// consumes the reserved capacity.
    ///
    /// Dropping the [`OwnedPermit`] without sending a message releases the
    /// capacity back to the channel.
    ///
    /// # Cancel safety
    ///
    /// This channel uses a queue to ensure that calls to `send` and `reserve`