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