Skip to content

Commit

Permalink
Auto merge of rust-lang#115753 - tgross35:threadinfo-refactor, r=thomcc
Browse files Browse the repository at this point in the history
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
  • Loading branch information
bors committed Sep 20, 2023
2 parents 62d9034 + 207b609 commit ed33e40
Showing 1 changed file with 21 additions and 16 deletions.
37 changes: 21 additions & 16 deletions library/std/src/sys_common/thread_info.rs
Original file line number Diff line number Diff line change
@@ -1,46 +1,51 @@
#![allow(dead_code)] // stack_guard isn't used right now on all platforms

use crate::cell::RefCell;
use crate::cell::OnceCell;
use crate::sys::thread::guard::Guard;
use crate::thread::Thread;

struct ThreadInfo {
stack_guard: Option<Guard>,
thread: Thread,
stack_guard: OnceCell<Guard>,
thread: OnceCell<Thread>,
}

thread_local! { static THREAD_INFO: RefCell<Option<ThreadInfo>> = const { RefCell::new(None) } }
thread_local! {
static THREAD_INFO: ThreadInfo = const { ThreadInfo {
stack_guard: OnceCell::new(),
thread: OnceCell::new()
} };
}

impl ThreadInfo {
fn with<R, F>(f: F) -> Option<R>
where
F: FnOnce(&mut ThreadInfo) -> R,
F: FnOnce(&Thread, &OnceCell<Guard>) -> R,
{
THREAD_INFO
.try_with(move |thread_info| {
let mut thread_info = thread_info.borrow_mut();
let thread_info = thread_info.get_or_insert_with(|| ThreadInfo {
stack_guard: None,
thread: Thread::new(None),
});
f(thread_info)
let thread = thread_info.thread.get_or_init(|| Thread::new(None));
f(thread, &thread_info.stack_guard)
})
.ok()
}
}

pub fn current_thread() -> Option<Thread> {
ThreadInfo::with(|info| info.thread.clone())
ThreadInfo::with(|thread, _| thread.clone())
}

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

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

0 comments on commit ed33e40

Please sign in to comment.