1#![deny(missing_docs)]
9
10use std::cell::Cell;
11
12bitflags! {
13 #[derive(Clone, Copy, Default, Debug, Eq, PartialEq)]
15 pub struct ThreadState: u32 {
16 const SCRIPT = 0x01;
18 const LAYOUT = 0x02;
20
21 const IN_WORKER = 0x0100;
24
25 const IN_GC = 0x0200;
27 }
28}
29
30impl ThreadState {
31 pub fn is_worker(self) -> bool {
33 self.contains(ThreadState::IN_WORKER)
34 }
35
36 pub fn is_script(self) -> bool {
38 self.contains(ThreadState::SCRIPT)
39 }
40
41 pub fn is_layout(self) -> bool {
43 self.contains(ThreadState::LAYOUT)
44 }
45}
46
47thread_local!(static STATE: Cell<Option<ThreadState>> = const { Cell::new(None) });
48
49pub fn initialize(initialize_to: ThreadState) {
51 STATE.with(|state| {
52 if let Some(current_state) = state.get() {
53 if initialize_to != current_state {
54 panic!("Thread state already initialized as {:?}", current_state);
55 }
56 }
57 state.set(Some(initialize_to));
58 });
59}
60
61pub fn initialize_layout_worker_thread() {
63 initialize(ThreadState::LAYOUT | ThreadState::IN_WORKER);
64}
65
66pub fn get() -> ThreadState {
68 STATE.with(|state| state.get().unwrap_or_default())
69}
70
71pub fn enter(additional_flags: ThreadState) {
73 STATE.with(|state| {
74 let current_state = state.get().unwrap_or_default();
75 debug_assert!(!current_state.intersects(additional_flags));
76 state.set(Some(current_state | additional_flags));
77 })
78}
79
80pub fn exit(flags_to_remove: ThreadState) {
82 STATE.with(|state| {
83 let current_state = state.get().unwrap_or_default();
84 debug_assert!(current_state.contains(flags_to_remove));
85 state.set(Some(current_state & !flags_to_remove));
86 })
87}