1use crate::runtime::context;
2
3use std::fmt;
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///
19/// **Note**: This is an [unstable API][unstable]. The public API of this type
20/// may break in 1.x releases. See [the documentation on unstable
21/// features][unstable] for details.
22///
23/// [unstable]: crate#unstable-features
24#[cfg_attr(docsrs, doc(cfg(all(feature = "rt", tokio_unstable))))]
25#[cfg_attr(not(tokio_unstable), allow(unreachable_pub))]
26#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
27pub struct Id(pub(crate) u64);
28
29/// Returns the [`Id`] of the currently running task.
30///
31/// # Panics
32///
33/// This function panics if called from outside a task. Please note that calls
34/// to `block_on` do not have task IDs, so the method will panic if called from
35/// within a call to `block_on`. For a version of this function that doesn't
36/// panic, see [`task::try_id()`](crate::runtime::task::try_id()).
37///
38/// **Note**: This is an [unstable API][unstable]. The public API of this type
39/// may break in 1.x releases. See [the documentation on unstable
40/// features][unstable] for details.
41///
42/// [task ID]: crate::task::Id
43/// [unstable]: crate#unstable-features
44#[cfg_attr(not(tokio_unstable), allow(unreachable_pub))]
45#[track_caller]
46pub fn id() -> Id {
47 context::current_task_id().expect("Can't get a task id when not inside a task")
48}
49
50/// Returns the [`Id`] of the currently running task, or `None` if called outside
51/// of a task.
52///
53/// This function is similar to [`task::id()`](crate::runtime::task::id()), except
54/// that it returns `None` rather than panicking if called outside of a task
55/// context.
56///
57/// **Note**: This is an [unstable API][unstable]. The public API of this type
58/// may break in 1.x releases. See [the documentation on unstable
59/// features][unstable] for details.
60///
61/// [task ID]: crate::task::Id
62/// [unstable]: crate#unstable-features
63#[cfg_attr(not(tokio_unstable), allow(unreachable_pub))]
64#[track_caller]
65pub fn try_id() -> Option<Id> {
66 context::current_task_id()
67}
68
69impl fmt::Display for Id {
70 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
71 self.0.fmt(f)
72 }
73}
74
75impl Id {
76 pub(crate) fn next() -> Self {
77 use crate::loom::sync::atomic::Ordering::Relaxed;
78 use crate::loom::sync::atomic::StaticAtomicU64;
79
80 #[cfg(all(test, loom))]
81 {
82 crate::loom::lazy_static! {
83 static ref NEXT_ID: StaticAtomicU64 = StaticAtomicU64::new(1);
84 }
85 Self(NEXT_ID.fetch_add(1, Relaxed))
86 }
87
88 #[cfg(not(all(test, loom)))]
89 {
90 static NEXT_ID: StaticAtomicU64 = StaticAtomicU64::new(1);
91 Self(NEXT_ID.fetch_add(1, Relaxed))
92 }
93 }
94
95 pub(crate) fn as_u64(&self) -> u64 {
96 self.0
97 }
98}
99