#![allow(dead_code)] // stack_guard isn't used right now on all platforms use crate::cell::OnceCell; use crate::sys::thread::guard::Guard; use crate::thread::Thread; struct ThreadInfo { stack_guard: OnceCell, thread: OnceCell, } thread_local! { static THREAD_INFO: ThreadInfo = const { ThreadInfo { stack_guard: OnceCell::new(), thread: OnceCell::new() } }; } impl ThreadInfo { fn with(f: F) -> Option where F: FnOnce(&Thread, &OnceCell) -> R, { THREAD_INFO .try_with(move |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 { ThreadInfo::with(|thread, _| thread.clone()) } pub fn stack_guard() -> Option { 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, thread: Thread) { THREAD_INFO.with(move |thread_info| { 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(); }); }