Skip to content

Commit ed33e40

Browse files
committed
Auto merge of #115753 - tgross35:threadinfo-refactor, r=thomcc
Refactor `thread_info` to remove the `RefCell` `thread_info` currently uses `RefCell`-based initialization. Refactor this to use `OnceCell` instead which is more performant and better suits the needs of one-time initialization. This is nobody's bottleneck but OnceCell checks are a single `cmp` vs. `RefCell<Option>` needing runtime logic
2 parents 62d9034 + 207b609 commit ed33e40

File tree

1 file changed

+21
-16
lines changed

1 file changed

+21
-16
lines changed
+21-16
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,51 @@
11
#![allow(dead_code)] // stack_guard isn't used right now on all platforms
22

3-
use crate::cell::RefCell;
3+
use crate::cell::OnceCell;
44
use crate::sys::thread::guard::Guard;
55
use crate::thread::Thread;
66

77
struct ThreadInfo {
8-
stack_guard: Option<Guard>,
9-
thread: Thread,
8+
stack_guard: OnceCell<Guard>,
9+
thread: OnceCell<Thread>,
1010
}
1111

12-
thread_local! { static THREAD_INFO: RefCell<Option<ThreadInfo>> = const { RefCell::new(None) } }
12+
thread_local! {
13+
static THREAD_INFO: ThreadInfo = const { ThreadInfo {
14+
stack_guard: OnceCell::new(),
15+
thread: OnceCell::new()
16+
} };
17+
}
1318

1419
impl ThreadInfo {
1520
fn with<R, F>(f: F) -> Option<R>
1621
where
17-
F: FnOnce(&mut ThreadInfo) -> R,
22+
F: FnOnce(&Thread, &OnceCell<Guard>) -> R,
1823
{
1924
THREAD_INFO
2025
.try_with(move |thread_info| {
21-
let mut thread_info = thread_info.borrow_mut();
22-
let thread_info = thread_info.get_or_insert_with(|| ThreadInfo {
23-
stack_guard: None,
24-
thread: Thread::new(None),
25-
});
26-
f(thread_info)
26+
let thread = thread_info.thread.get_or_init(|| Thread::new(None));
27+
f(thread, &thread_info.stack_guard)
2728
})
2829
.ok()
2930
}
3031
}
3132

3233
pub fn current_thread() -> Option<Thread> {
33-
ThreadInfo::with(|info| info.thread.clone())
34+
ThreadInfo::with(|thread, _| thread.clone())
3435
}
3536

3637
pub fn stack_guard() -> Option<Guard> {
37-
ThreadInfo::with(|info| info.stack_guard.clone()).and_then(|o| o)
38+
ThreadInfo::with(|_, guard| guard.get().cloned()).flatten()
3839
}
3940

41+
/// Set new thread info, panicking if it has already been initialized
42+
#[allow(unreachable_code, unreachable_patterns)] // some platforms don't use stack_guard
4043
pub fn set(stack_guard: Option<Guard>, thread: Thread) {
4144
THREAD_INFO.with(move |thread_info| {
42-
let mut thread_info = thread_info.borrow_mut();
43-
rtassert!(thread_info.is_none());
44-
*thread_info = Some(ThreadInfo { stack_guard, thread });
45+
rtassert!(thread_info.stack_guard.get().is_none() && thread_info.thread.get().is_none());
46+
if let Some(guard) = stack_guard {
47+
thread_info.stack_guard.set(guard).unwrap();
48+
}
49+
thread_info.thread.set(thread).unwrap();
4550
});
4651
}

0 commit comments

Comments
 (0)