Repository: tokio-rs/tokio
File: tokio-util/src/task/join_queue.rs (Rust)

Code before:
            let jh = self.0.pop_front().unwrap().detach();
            let res = jh.now_or_never().unwrap();
            Some(res)
        } else {
            None
        }
    }

    /// Tries to join the next task in FIFO order if it has completed and return its output,
    /// along with its [task ID].
    ///
    /// Returns `None` if the queue is empty or if the next task is not yet ready.
    ///
    /// When this method returns an error, then the id of the task that failed can be accessed
    /// using the [`JoinError::id`] method.
    ///
    /// [task ID]: tokio::task::Id
    /// [`JoinError::id`]: fn@tokio::task::JoinError::id
    pub fn try_join_next_with_id(&mut self) -> Option<Result<(Id, T), JoinError>> {
        if self.0.front()?.is_finished() {
            // Use `detach` to avoid calling `abort` on a task that has already completed.
            // Dropping `AbortOnDropHandle` would abort the task, but since it is finished,
            // we only need to drop the `JoinHandle` for cleanup.
            let jh = self.0.pop_front().unwrap().detach();
            let id = jh.id();
            let res = jh.now_or_never().unwrap();
            Some(res.map(|output| (id, output)))
        } else {
            None
        }
    }

    /// Aborts all tasks and waits for them to finish shutting down.
    ///
    /// Calling this method is equivalent to calling [`abort_all`] and then calling [`join_next`] in
    /// a loop until it returns `None`.
    ///
    /// This method ignores any panics in the tasks shutting down. When this call returns, the
    /// [`JoinQueue`] will be empty.
    ///
    /// [`abort_all`]: fn@Self::abort_all
    /// [`join_next`]: fn@Self::join_next
    pub async fn shutdown(&mut self) {
        self.abort_all();
        while self.join_next().await.is_some() {}
    }

    /// Awaits the completion of all tasks in this [`JoinQueue`], returning a vector of their results.
    ///
    /// The results will be stored in the order they were spawned, not the order they completed.
    /// This is a convenience method that is equivalent to calling [`join_next`] in

Review comment (suggestion):
A short comment here for `unwrap` would be better.

Code after:
        // disable budgeting when we want to check for the `JoinHandle` readiness.
        let jh = std::pin::pin!(tokio::task::coop::unconstrained(jh));
        if let Poll::Ready(res) = jh.poll(&mut cx) {
            Some(res)
        } else {
            None
        }
    }

    /// Tries to join the next task in FIFO order if it has completed.
    ///
    /// Returns `None` if the queue is empty or if the next task is not yet ready.
    pub fn try_join_next(&mut self) -> Option<Result<T, JoinError>> {
        let jh = self.0.front_mut()?;
        let res = Self::try_poll_handle(jh)?;
        // Use `detach` to avoid calling `abort` on a task that has already completed.
        // Dropping `AbortOnDropHandle` would abort the task, but since it is finished,
        // we only need to drop the `JoinHandle` for cleanup.
        drop(self.0.pop_front().unwrap().detach());
        Some(res)
    }

    /// Tries to join the next task in FIFO order if it has completed and return its output,
    /// along with its [task ID].
    ///
    /// Returns `None` if the queue is empty or if the next task is not yet ready.
    ///
    /// When this method returns an error, then the id of the task that failed can be accessed
    /// using the [`JoinError::id`] method.
    ///
    /// [task ID]: tokio::task::Id
    /// [`JoinError::id`]: fn@tokio::task::JoinError::id
    pub fn try_join_next_with_id(&mut self) -> Option<Result<(Id, T), JoinError>> {
        let jh = self.0.front_mut()?;
        let res = Self::try_poll_handle(jh)?;
        // Use `detach` to avoid calling `abort` on a task that has already completed.
        // Dropping `AbortOnDropHandle` would abort the task, but since it is finished,
        // we only need to drop the `JoinHandle` for cleanup.
        let jh = self.0.pop_front().unwrap().detach();
        let id = jh.id();
        drop(jh);
        Some(res.map(|output| (id, output)))
    }

    /// Aborts all tasks and waits for them to finish shutting down.
    ///
    /// Calling this method is equivalent to calling [`abort_all`] and then calling [`join_next`] in
    /// a loop until it returns `None`.
    ///
    /// This method ignores any panics in the tasks shutting down. When this call returns, the
    /// [`JoinQueue`] will be empty.