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