1 use crate::runtime::context;
2
3 use 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)]
20 pub 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]
id() -> Id33 pub 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]
try_id() -> Option<Id>46 pub fn try_id() -> Option<Id> {
47 context::current_task_id()
48 }
49
50 impl fmt::Display for Id {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result51 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
52 self.0.fmt(f)
53 }
54 }
55
56 impl Id {
next() -> Self57 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
as_u64(&self) -> u6477 pub(crate) fn as_u64(&self) -> u64 {
78 self.0.get()
79 }
80 }
81