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
use std::{cell::Cell, ptr, sync::Arc};
#[cfg(test)]
mod tests;
/// A unique identifier for a thread.
///
/// This type allows you to
///
/// 1. acquire the current thread id,
/// 2. later check if you are still on the same thread.
#[derive(Clone)]
pub(crate) struct ThreadId {
id: Arc<usize>,
}
thread_local! {
static THREAD_ID: ThreadId = {
let id = ThreadId {
id: Arc::new(0),
};
THREAD_ID_ADDR.set(id.addr());
id
};
static THREAD_ID_ADDR: Cell<*const usize> = const { Cell::new(ptr::null()) };
}
impl ThreadId {
/// Returns the identifier of the current thread.
pub(crate) fn current() -> Self {
THREAD_ID.with(|tid| tid.clone())
}
/// Returns the address of the contained usize.
#[inline]
fn addr(&self) -> *const usize {
let reference: &usize = &self.id;
reference as *const usize
}
/// Returns whether the current thread is the thread on which [`Self::current`] was called.
#[inline]
pub(crate) fn is_current(&self) -> bool {
// - If self was created on the current thread, then self was cloned from
// THREAD_ID. Therefore self.id is a clone of THREAD_ID.id which means that the
// contained usize have the same address and this function returns true.
// - Assume that self was created for a different thread, T. For any thread X,
// write X.THREAD_ID for the THREAD_ID object in that thread.
// - If T.THREAD_ID was allocated without synchronization with CURRENT.THREAD_ID,
// then they cannot use the same Arc address and therefore this function
// returns false.
// - Otherwise, if T.THREAD_ID was allocated before CURRENT.THREAD_ID, then a
// clone of the T.THREAD_ID Arc existed before and after CURRENT.THREAD was
// allocated. (Note: Even if the thread T has already terminated, self still
// contains a clone of the Arc.) Therefore they must have different addresses
// and this function return false.
// - Otherwise, if CURRENT.THREAD_ID was allocated before T.THREAD_ID, then
// CURRENT.THREAD_ID existed before T.THREAD_ID was allocated and still exists.
// Therefore they must have different addresses and this function return false.
self.addr() == THREAD_ID_ADDR.get()
}
#[inline]
pub(crate) fn is_not_current(&self) -> bool {
!self.is_current()
}
}