From 7f455b2d9334c89dba03d9dd49a19cc56b791ecd Mon Sep 17 00:00:00 2001 From: Sean Oxley <13091705+OxleyS@users.noreply.github.com> Date: Mon, 15 Sep 2025 19:18:16 +0900 Subject: [PATCH] task: clarify the task ID reuse guarantees (#7577) --- tokio/src/runtime/task/id.rs | 16 ++++++++++++++-- tokio/src/task/join_set.rs | 10 ++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/tokio/src/runtime/task/id.rs b/tokio/src/runtime/task/id.rs index df946f2cf..3fcd9d2d4 100644 --- a/tokio/src/runtime/task/id.rs +++ b/tokio/src/runtime/task/id.rs @@ -5,16 +5,28 @@ use std::{fmt, num::NonZeroU64}; /// An opaque ID that uniquely identifies a task relative to all other currently /// running tasks. /// +/// A task's ID may be re-used for another task only once *both* of the +/// following happen: +/// 1. The task itself exits. +/// 2. There is no active [`JoinHandle`] associated with this task. +/// +/// A [`JoinHandle`] is considered active in the following situations: +/// - You are explicitly holding a [`JoinHandle`], [`AbortHandle`], or +/// `tokio_util::task::AbortOnDropHandle`. +/// - The task is being tracked by a [`JoinSet`] or `tokio_util::task::JoinMap`. +/// /// # Notes /// -/// - Task IDs are unique relative to other *currently running* tasks. When a -/// task completes, the same ID may be used for another task. /// - Task IDs are *not* sequential, and do not indicate the order in which /// tasks are spawned, what runtime a task is spawned on, or any other data. /// - The task ID of the currently running task can be obtained from inside the /// task via the [`task::try_id()`](crate::task::try_id()) and /// [`task::id()`](crate::task::id()) functions and from outside the task via /// the [`JoinHandle::id()`](crate::task::JoinHandle::id()) function. +/// +/// [`JoinHandle`]: crate::task::JoinHandle +/// [`AbortHandle`]: crate::task::AbortHandle +/// [`JoinSet`]: crate::task::JoinSet #[cfg_attr(docsrs, doc(cfg(all(feature = "rt"))))] #[derive(Clone, Copy, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)] pub struct Id(pub(crate) NonZeroU64); diff --git a/tokio/src/task/join_set.rs b/tokio/src/task/join_set.rs index 21367c989..1f8fc6a4e 100644 --- a/tokio/src/task/join_set.rs +++ b/tokio/src/task/join_set.rs @@ -50,6 +50,16 @@ use crate::util::IdleNotifiedSet; /// } /// } /// ``` +/// +/// # Task ID guarantees +/// +/// While a task is tracked in a `JoinSet`, that task's ID is unique relative +/// to all other running tasks in Tokio. For this purpose, tracking a task in a +/// `JoinSet` is equivalent to holding a [`JoinHandle`] to it. See the [task ID] +/// documentation for more info. +/// +/// [`JoinHandle`]: crate::task::JoinHandle +/// [task ID]: crate::task::Id #[cfg_attr(docsrs, doc(cfg(feature = "rt")))] pub struct JoinSet { inner: IdleNotifiedSet>,