1 | #![allow (dead_code)] // stack_guard isn't used right now on all platforms |
2 | |
3 | use crate::cell::OnceCell; |
4 | use crate::sys::thread::guard::Guard; |
5 | use crate::thread::Thread; |
6 | |
7 | struct ThreadInfo { |
8 | stack_guard: OnceCell<Guard>, |
9 | thread: OnceCell<Thread>, |
10 | } |
11 | |
12 | thread_local! { |
13 | static THREAD_INFO: ThreadInfo = const { ThreadInfo { |
14 | stack_guard: OnceCell::new(), |
15 | thread: OnceCell::new() |
16 | } }; |
17 | } |
18 | |
19 | impl 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 | |
33 | pub fn current_thread() -> Option<Thread> { |
34 | ThreadInfo::with(|thread: &Thread, _| thread.clone()) |
35 | } |
36 | |
37 | pub 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 |
43 | pub 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 | |