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/// # Notes
9///
10/// - Task IDs are unique relative to other *currently running* tasks. When a
11///   task completes, the same ID may be used for another task.
12/// - Task IDs are *not* sequential, and do not indicate the order in which
13///   tasks are spawned, what runtime a task is spawned on, or any other data.
14/// - The task ID of the currently running task can be obtained from inside the
15///   task via the [`task::try_id()`](crate::task::try_id()) and
16///   [`task::id()`](crate::task::id()) functions and from outside the task via
17///   the [`JoinHandle::id()`](crate::task::JoinHandle::id()) function.
18#[cfg_attr(docsrs, doc(cfg(all(feature = "rt"))))]
19#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
20pub struct Id(pub(crate) NonZeroU64);
21
22/// Returns the [`Id`] of the currently running task.
23///
24/// # Panics
25///
26/// This function panics if called from outside a task. Please note that calls
27/// to `block_on` do not have task IDs, so the method will panic if called from
28/// within a call to `block_on`. For a version of this function that doesn't
29/// panic, see [`task::try_id()`](crate::runtime::task::try_id()).
30///
31/// [task ID]: crate::task::Id
32#[track_caller]
33pub fn id() -> Id {
34    context::current_task_id().expect("Can't get a task id when not inside a task")
35}
36
37/// Returns the [`Id`] of the currently running task, or `None` if called outside
38/// of a task.
39///
40/// This function is similar to  [`task::id()`](crate::runtime::task::id()), except
41/// that it returns `None` rather than panicking if called outside of a task
42/// context.
43///
44/// [task ID]: crate::task::Id
45#[track_caller]
46pub fn try_id() -> Option<Id> {
47    context::current_task_id()
48}
49
50impl fmt::Display for Id {
51    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
52        self.0.fmt(f)
53    }
54}
55
56impl Id {
57    pub(crate) fn next() -> Self {
58        use crate::loom::sync::atomic::Ordering::Relaxed;
59        use crate::loom::sync::atomic::StaticAtomicU64;
60
61        #[cfg(all(test, loom))]
62        crate::loom::lazy_static! {
63            static ref NEXT_ID: StaticAtomicU64 = StaticAtomicU64::new(1);
64        }
65
66        #[cfg(not(all(test, loom)))]
67        static NEXT_ID: StaticAtomicU64 = StaticAtomicU64::new(1);
68
69        loop {
70            let id = NEXT_ID.fetch_add(1, Relaxed);
71            if let Some(id) = NonZeroU64::new(id) {
72                return Self(id);
73            }
74        }
75    }
76
77    pub(crate) fn as_u64(&self) -> u64 {
78        self.0.get()
79    }
80}