Source code

Revision control

Other Tools

1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
* License, v. 2.0. If a copy of the MPL was not distributed with this
3
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5
//! Supports dynamic assertions in about what sort of thread is running and
6
//! what state it's in.
7
8
#![deny(missing_docs)]
9
10
use std::cell::RefCell;
11
12
bitflags! {
13
/// A thread state flag, used for multiple assertions.
14
pub struct ThreadState: u32 {
15
/// Whether we're in a script thread.
16
const SCRIPT = 0x01;
17
/// Whether we're in a layout thread.
18
const LAYOUT = 0x02;
19
20
/// Whether we're in a script worker thread (actual web workers), or in
21
/// a layout worker thread.
22
const IN_WORKER = 0x0100;
23
24
/// Whether the current thread is going through a GC.
25
const IN_GC = 0x0200;
26
}
27
}
28
29
macro_rules! thread_types ( ( $( $fun:ident = $flag:path ; )* ) => (
30
impl ThreadState {
31
/// Whether the current thread is a worker thread.
32
pub fn is_worker(self) -> bool {
33
self.contains(ThreadState::IN_WORKER)
34
}
35
36
$(
37
#[allow(missing_docs)]
38
pub fn $fun(self) -> bool {
39
self.contains($flag)
40
}
41
)*
42
}
43
));
44
45
thread_types! {
46
is_script = ThreadState::SCRIPT;
47
is_layout = ThreadState::LAYOUT;
48
}
49
50
thread_local!(static STATE: RefCell<Option<ThreadState>> = RefCell::new(None));
51
52
/// Initializes the current thread state.
53
pub fn initialize(x: ThreadState) {
54
STATE.with(|ref k| {
55
if let Some(ref s) = *k.borrow() {
56
if x != *s {
57
panic!("Thread state already initialized as {:?}", s);
58
}
59
}
60
*k.borrow_mut() = Some(x);
61
});
62
}
63
64
/// Initializes the current thread as a layout worker thread.
65
pub fn initialize_layout_worker_thread() {
66
initialize(ThreadState::LAYOUT | ThreadState::IN_WORKER);
67
}
68
69
/// Gets the current thread state.
70
pub fn get() -> ThreadState {
71
let state = STATE.with(|ref k| {
72
match *k.borrow() {
73
None => ThreadState::empty(), // Unknown thread.
74
Some(s) => s,
75
}
76
});
77
78
state
79
}
80
81
/// Enters into a given temporary state. Panics if re-entring.
82
pub fn enter(x: ThreadState) {
83
let state = get();
84
debug_assert!(!state.intersects(x));
85
STATE.with(|ref k| {
86
*k.borrow_mut() = Some(state | x);
87
})
88
}
89
90
/// Exits a given temporary state.
91
pub fn exit(x: ThreadState) {
92
let state = get();
93
debug_assert!(state.contains(x));
94
STATE.with(|ref k| {
95
*k.borrow_mut() = Some(state & !x);
96
})
97
}