starnix_sync/
thread_affinity.rs1#[cfg(feature = "detect_lock_dep_cycles")]
6mod tracking {
7 use std::sync::atomic::{AtomicUsize, Ordering};
8
9 static NEXT_THREAD_ID: AtomicUsize = AtomicUsize::new(1);
10
11 thread_local! {
12 static THREAD_ID: usize = NEXT_THREAD_ID.fetch_add(1, Ordering::Relaxed);
13 }
14
15 fn current_thread_id() -> usize {
16 THREAD_ID.with(|id| *id)
17 }
18
19 pub struct ThreadAffinityState {
20 owner: AtomicUsize,
21 }
22
23 impl ThreadAffinityState {
24 pub const fn new() -> Self {
25 Self { owner: AtomicUsize::new(0) }
26 }
27
28 #[inline(always)]
29 pub fn attach(&self) -> ThreadAffinityToken<'_> {
30 let id = current_thread_id();
31 let previous = self.owner.swap(id, Ordering::Relaxed);
32 assert_eq!(previous, 0, "ThreadAffinity: Object is already attached to a thread!");
33 ThreadAffinityToken { state: self }
34 }
35
36 #[inline(always)]
37 pub fn assert_attached(&self) {
38 let id = current_thread_id();
39 assert_eq!(
40 self.owner.load(Ordering::Relaxed),
41 id,
42 "ThreadAffinity: Object is not attached to the current thread!"
43 );
44 }
45
46 #[inline(always)]
47 pub fn assert_not_attached(&self) {
48 let id = current_thread_id();
49 assert_ne!(
50 self.owner.load(Ordering::Relaxed),
51 id,
52 "ThreadAffinity: Object is already attached to the current thread!"
53 );
54 }
55 }
56
57 pub struct ThreadAffinityToken<'a> {
58 state: &'a ThreadAffinityState,
59 }
60
61 impl<'a> Drop for ThreadAffinityToken<'a> {
62 fn drop(&mut self) {
63 self.state.owner.store(0, Ordering::Relaxed);
64 }
65 }
66}
67
68#[cfg(not(feature = "detect_lock_dep_cycles"))]
69mod tracking {
70 pub struct ThreadAffinityState {}
71
72 impl ThreadAffinityState {
73 #[inline(always)]
74 pub const fn new() -> Self {
75 Self {}
76 }
77
78 #[inline(always)]
79 pub fn attach(&self) -> ThreadAffinityToken<'_> {
80 ThreadAffinityToken { _state: self }
81 }
82
83 #[inline(always)]
84 pub fn assert_attached(&self) {}
85
86 #[inline(always)]
87 pub fn assert_not_attached(&self) {}
88 }
89
90 pub struct ThreadAffinityToken<'a> {
91 _state: &'a ThreadAffinityState,
92 }
93}
94
95pub struct ThreadAffinity {
101 state: tracking::ThreadAffinityState,
102}
103
104impl ThreadAffinity {
105 pub const fn new() -> Self {
106 Self { state: tracking::ThreadAffinityState::new() }
107 }
108
109 #[inline(always)]
113 pub fn attach(&self) -> ThreadAffinityGuard<'_> {
114 ThreadAffinityGuard { _token: self.state.attach() }
115 }
116
117 #[inline(always)]
121 pub fn assert_attached(&self) {
122 self.state.assert_attached();
123 }
124
125 #[inline(always)]
129 pub fn assert_not_attached(&self) {
130 self.state.assert_not_attached();
131 }
132}
133
134impl Default for ThreadAffinity {
135 fn default() -> Self {
136 Self::new()
137 }
138}
139
140pub struct ThreadAffinityGuard<'a> {
141 _token: tracking::ThreadAffinityToken<'a>,
142}