maitake/task/
id.rs

1use core::fmt;
2
3/// A unique identifier for a running [task].
4///
5/// A `TaskId` is an opaque object that uniquely identifies each [task]
6/// created during the lifetime of a program. `TaskIds`s are guaranteed not to
7/// be reused, even when a task terminates. A `TaskId` can be retrieved from the
8/// [`TaskRef::id`], [`JoinHandle::id`], and [`Task::id`] methods.
9///
10/// A `TaskId` does *not* increase the reference count of the [task] it
11/// references, and task IDs may persist even after the task they identify has
12/// completed and been deallocated.
13///
14/// [task]: crate::task
15/// [`TaskRef::id`]: crate::task::TaskRef::id
16/// [`JoinHandle::id`]: crate::task::JoinHandle::id
17/// [`Task::id`]: crate::task::Task::id
18#[derive(Copy, Clone, Eq, PartialEq, Hash)]
19pub struct TaskId(u64);
20
21impl TaskId {
22    pub(crate) fn next() -> Self {
23        // Don't use loom atomics, since this has to go in a static.
24        use portable_atomic::{AtomicU64, Ordering::Relaxed};
25
26        // ID 0 is reserved for stub tasks.
27        static NEXT_ID: AtomicU64 = AtomicU64::new(1);
28        let id = NEXT_ID.fetch_add(1, Relaxed);
29
30        debug_assert!(id > 0, "64-bit task ID counter should not overflow!");
31        Self(id)
32    }
33
34    #[must_use]
35    #[inline]
36    pub(crate) const fn stub() -> Self {
37        Self(0)
38    }
39
40    #[allow(dead_code)]
41    #[must_use]
42    #[inline]
43    pub(crate) fn is_stub(self) -> bool {
44        self.0 == 0
45    }
46
47    #[inline]
48    #[allow(dead_code)] // currently only used when tracing is enabled
49    pub(crate) fn as_u64(self) -> u64 {
50        self.0
51    }
52}
53
54impl fmt::UpperHex for TaskId {
55    #[inline]
56    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
57        f.write_str("TaskId(")?;
58        fmt::UpperHex::fmt(&self.0, f)?;
59        f.write_str(")")
60    }
61}
62
63impl fmt::LowerHex for TaskId {
64    #[inline]
65    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66        f.write_str("TaskId(")?;
67        fmt::LowerHex::fmt(&self.0, f)?;
68        f.write_str(")")
69    }
70}
71
72impl fmt::Debug for TaskId {
73    #[inline]
74    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
75        f.write_str("TaskId(")?;
76        fmt::Debug::fmt(&self.0, f)?;
77        f.write_str(")")
78    }
79}
80
81impl fmt::Display for TaskId {
82    #[inline]
83    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
84        fmt::Display::fmt(&self.0, f)
85    }
86}
87
88// ==== PartialEq impls for refs ====
89
90impl PartialEq<&'_ TaskId> for TaskId {
91    #[inline]
92    fn eq(&self, other: &&Self) -> bool {
93        self.0 == other.0
94    }
95}
96
97impl PartialEq<TaskId> for &'_ TaskId {
98    #[inline]
99    fn eq(&self, other: &TaskId) -> bool {
100        self.0 == other.0
101    }
102}