1#![warn(missing_docs)]
29
30#[cfg(unix)]
31extern crate libc;
32
33#[cfg(windows)]
34extern crate windows_sys;
35
36#[inline]
42pub fn get() -> usize {
43 get_internal()
44}
45
46#[cfg(all(
47 unix,
48 not(any(
49 target_os = "macos",
50 target_os = "ios",
51 target_os = "tvos",
52 target_os = "watchos"
53 ))
54))]
55#[inline]
56fn get_internal() -> usize {
57 unsafe { libc::pthread_self() as usize }
58}
59
60#[cfg(all(
61 unix,
62 any(
63 target_os = "macos",
64 target_os = "ios",
65 target_os = "tvos",
66 target_os = "watchos"
67 )
68))]
69#[inline]
70fn get_internal() -> usize {
71 let mut tid: u64 = 0;
72 unsafe {
73 libc::pthread_threadid_np(libc::pthread_self(), &mut tid as *mut u64);
74 };
75 tid as usize
76}
77
78#[cfg(windows)]
79#[inline]
80fn get_internal() -> usize {
81 unsafe { windows_sys::Win32::System::Threading::GetCurrentThreadId() as usize }
82}
83
84#[cfg(all(
85 target_arch = "wasm32",
86 target_vendor = "unknown",
87 target_os = "unknown",
88 not(target_feature = "atomics"),
89))]
90#[inline]
91fn get_internal() -> usize {
92 0
93}
94
95#[cfg(any(
96 target_env = "sgx",
97 all(
98 target_arch = "wasm32",
99 target_vendor = "unknown",
100 target_os = "unknown",
101 target_feature = "atomics",
102 )
103))]
104#[inline]
105fn get_internal() -> usize {
106 use std::sync::atomic::{AtomicUsize, Ordering};
107
108 static COUNTER: AtomicUsize = AtomicUsize::new(0);
109
110 thread_local! {
111 static ID: usize = COUNTER.fetch_add(1, Ordering::Relaxed);
112 }
113
114 ID.with(|id| *id)
115}
116
117#[test]
118fn distinct_threads_have_distinct_ids() {
119 use std::sync::mpsc;
120 use std::thread;
121
122 let (tx, rx) = mpsc::channel();
123 thread::spawn(move || tx.send(crate::get()).unwrap()).join().unwrap();
124
125 let main_tid = crate::get();
126 let other_tid = rx.recv().unwrap();
127 assert!(main_tid != other_tid);
128}