tokio/runtime/task/id.rs
1use crate::runtime::context;
2
3use std::{fmt, num::NonZeroU64};
4
5/// An opaque ID that uniquely identifies a task relative to all other currently
6/// running tasks.
7///
8/// A task's ID may be re-used for another task only once *both* of the
9/// following happen:
10/// 1. The task itself exits.
11/// 2. There is no active [`JoinHandle`] associated with this task.
12///
13/// A [`JoinHandle`] is considered active in the following situations:
14/// - You are explicitly holding a [`JoinHandle`], [`AbortHandle`], or
15/// `tokio_util::task::AbortOnDropHandle`.
16/// - The task is being tracked by a [`JoinSet`] or `tokio_util::task::JoinMap`.
17///
18/// # Notes
19///
20/// - Task IDs are *not* sequential, and do not indicate the order in which
21/// tasks are spawned, what runtime a task is spawned on, or any other data.
22/// - The task ID of the currently running task can be obtained from inside the
23/// task via the [`task::try_id()`](crate::task::try_id()) and
24/// [`task::id()`](crate::task::id()) functions and from outside the task via
25/// the [`JoinHandle::id()`](crate::task::JoinHandle::id()) function.
26///
27/// [`JoinHandle`]: crate::task::JoinHandle
28/// [`AbortHandle`]: crate::task::AbortHandle
29/// [`JoinSet`]: crate::task::JoinSet
30#[cfg_attr(docsrs, doc(cfg(all(feature = "rt"))))]
31#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)]
32pub struct Id(pub(crate) NonZeroU64);
33
34/// Returns the [`Id`] of the currently running task.
35///
36/// # Panics
37///
38/// This function panics if called from outside a task. Please note that calls
39/// to `block_on` do not have task IDs, so the method will panic if called from
40/// within a call to `block_on`. For a version of this function that doesn't
41/// panic, see [`task::try_id()`](crate::runtime::task::try_id()).
42///
43/// [task ID]: crate::task::Id
44#[track_caller]
45pub fn id() -> Id {
46 context::current_task_id().expect("Can't get a task id when not inside a task")
47}
48
49/// Returns the [`Id`] of the currently running task, or `None` if called outside
50/// of a task.
51///
52/// This function is similar to [`task::id()`](crate::runtime::task::id()), except
53/// that it returns `None` rather than panicking if called outside of a task
54/// context.
55///
56/// [task ID]: crate::task::Id
57#[track_caller]
58pub fn try_id() -> Option<Id> {
59 context::current_task_id()
60}
61
62impl fmt::Display for Id {
63 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64 self.0.fmt(f)
65 }
66}
67
68impl Id {
69 pub(crate) fn next() -> Self {
70 use crate::loom::sync::atomic::Ordering::Relaxed;
71 use crate::loom::sync::atomic::StaticAtomicU64;
72
73 #[cfg(all(test, loom))]
74 crate::loom::lazy_static! {
75 static ref NEXT_ID: StaticAtomicU64 = StaticAtomicU64::new(1);
76 }
77
78 #[cfg(not(all(test, loom)))]
79 static NEXT_ID: StaticAtomicU64 = StaticAtomicU64::new(1);
80
81 loop {
82 let id = NEXT_ID.fetch_add(1, Relaxed);
83 if let Some(id) = NonZeroU64::new(id) {
84 return Self(id);
85 }
86 }
87 }
88
89 pub(crate) fn as_u64(&self) -> u64 {
90 self.0.get()
91 }
92}