1#![allow(dead_code)] // stack_guard isn't used right now on all platforms
2
3use crate::cell::OnceCell;
4use crate::sys::thread::guard::Guard;
5use crate::thread::Thread;
6
7struct ThreadInfo {
8 stack_guard: OnceCell<Guard>,
9 thread: OnceCell<Thread>,
10}
11
12thread_local! {
13 static THREAD_INFO: ThreadInfo = const { ThreadInfo {
14 stack_guard: OnceCell::new(),
15 thread: OnceCell::new()
16 } };
17}
18
19impl ThreadInfo {
20 fn with<R, F>(f: F) -> Option<R>
21 where
22 F: FnOnce(&Thread, &OnceCell<Guard>) -> R,
23 {
24 THREAD_INFO
25 .try_with(move |thread_info: &ThreadInfo| {
26 let thread: &Thread = thread_info.thread.get_or_init(|| Thread::new(name:None));
27 f(thread, &thread_info.stack_guard)
28 })
29 .ok()
30 }
31}
32
33pub fn current_thread() -> Option<Thread> {
34 ThreadInfo::with(|thread: &Thread, _| thread.clone())
35}
36
37pub fn stack_guard() -> Option<Guard> {
38 ThreadInfo::with(|_, guard: &OnceCell>| guard.get().cloned()).flatten()
39}
40
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
43pub fn set(stack_guard: Option<Guard>, thread: Thread) {
44 THREAD_INFO.with(move |thread_info: &ThreadInfo| {
45 rtassert!(thread_info.stack_guard.get().is_none() && thread_info.thread.get().is_none());
46 if let Some(guard: Range) = stack_guard {
47 thread_info.stack_guard.set(guard).unwrap();
48 }
49 thread_info.thread.set(thread).unwrap();
50 });
51}
52