| #![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<Guard>, |
| thread: OnceCell<Thread>, |
| } |
| |
| 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(&Thread, &OnceCell<Guard>) -> 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<Thread> { |
| ThreadInfo::with(|thread, _| thread.clone()) |
| } |
| |
| pub fn stack_guard() -> Option<Guard> { |
| 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| { |
| 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(); |
| }); |
| } |