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 commit is contained in:
parent
5d62ab8981
commit
207b6091d4
@ -1,46 +1,51 @@
|
|||||||
#![allow(dead_code)] // stack_guard isn't used right now on all platforms
|
#![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::sys::thread::guard::Guard;
|
||||||
use crate::thread::Thread;
|
use crate::thread::Thread;
|
||||||
|
|
||||||
struct ThreadInfo {
|
struct ThreadInfo {
|
||||||
stack_guard: Option<Guard>,
|
stack_guard: OnceCell<Guard>,
|
||||||
thread: Thread,
|
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 {
|
impl ThreadInfo {
|
||||||
fn with<R, F>(f: F) -> Option<R>
|
fn with<R, F>(f: F) -> Option<R>
|
||||||
where
|
where
|
||||||
F: FnOnce(&mut ThreadInfo) -> R,
|
F: FnOnce(&Thread, &OnceCell<Guard>) -> R,
|
||||||
{
|
{
|
||||||
THREAD_INFO
|
THREAD_INFO
|
||||||
.try_with(move |thread_info| {
|
.try_with(move |thread_info| {
|
||||||
let mut thread_info = thread_info.borrow_mut();
|
let thread = thread_info.thread.get_or_init(|| Thread::new(None));
|
||||||
let thread_info = thread_info.get_or_insert_with(|| ThreadInfo {
|
f(thread, &thread_info.stack_guard)
|
||||||
stack_guard: None,
|
|
||||||
thread: Thread::new(None),
|
|
||||||
});
|
|
||||||
f(thread_info)
|
|
||||||
})
|
})
|
||||||
.ok()
|
.ok()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn current_thread() -> Option<Thread> {
|
pub fn current_thread() -> Option<Thread> {
|
||||||
ThreadInfo::with(|info| info.thread.clone())
|
ThreadInfo::with(|thread, _| thread.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stack_guard() -> Option<Guard> {
|
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) {
|
pub fn set(stack_guard: Option<Guard>, thread: Thread) {
|
||||||
THREAD_INFO.with(move |thread_info| {
|
THREAD_INFO.with(move |thread_info| {
|
||||||
let mut thread_info = thread_info.borrow_mut();
|
rtassert!(thread_info.stack_guard.get().is_none() && thread_info.thread.get().is_none());
|
||||||
rtassert!(thread_info.is_none());
|
if let Some(guard) = stack_guard {
|
||||||
*thread_info = Some(ThreadInfo { stack_guard, thread });
|
thread_info.stack_guard.set(guard).unwrap();
|
||||||
|
}
|
||||||
|
thread_info.thread.set(thread).unwrap();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user