use core::convert::TryInto;
use core::num::NonZeroUsize;
thread_local! {
static THREAD_MARKER: () = ();
}
#[derive(PartialEq, Eq, Debug, Clone, Copy)]
#[repr(transparent)]
pub(crate) struct ThreadId(pub(crate) NonZeroUsize);
impl ThreadId {
#[inline(always)]
pub(crate) const fn new(value: NonZeroUsize) -> Self {
Self(value)
}
#[inline]
pub(crate) fn current_thread() -> Self {
Self::new(
THREAD_MARKER
.try_with(|x| x as *const _ as usize)
.expect("the thread's local data has already been destroyed")
.try_into()
.expect("thread id should never be zero"),
)
}
}
#[cfg(test)]
mod tests {
use super::*;
use alloc::format;
use std::thread;
#[test]
fn test_thread_ids_eq() {
let a = ThreadId::current_thread();
let b = ThreadId::current_thread();
assert_eq!(a, b);
assert_eq!(format!("{:?}", &a), format!("{:?}", &b));
}
#[test]
fn test_thread_ids_ne() {
let a = ThreadId::current_thread();
let b = thread::spawn(move || ThreadId::current_thread())
.join()
.unwrap();
assert_ne!(a, b);
assert_ne!(format!("{:?}", &a), format!("{:?}", &b));
}
#[test]
fn test_thread_ids_clone() {
let a = ThreadId::current_thread();
let b = a.clone();
assert_eq!(a, b);
}
}