|
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