summaryrefslogtreecommitdiffstats
path: root/servo/components/style/thread_state.rs
diff options
context:
space:
mode:
Diffstat (limited to 'servo/components/style/thread_state.rs')
-rw-r--r--servo/components/style/thread_state.rs98
1 files changed, 98 insertions, 0 deletions
diff --git a/servo/components/style/thread_state.rs b/servo/components/style/thread_state.rs
new file mode 100644
index 0000000000..cb7cfd0d64
--- /dev/null
+++ b/servo/components/style/thread_state.rs
@@ -0,0 +1,98 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+
+//! Supports dynamic assertions in about what sort of thread is running and
+//! what state it's in.
+
+#![deny(missing_docs)]
+
+use std::cell::RefCell;
+
+bitflags! {
+ /// A thread state flag, used for multiple assertions.
+ #[derive(Clone, Copy, Eq, PartialEq)]
+ pub struct ThreadState: u32 {
+ /// Whether we're in a script thread.
+ const SCRIPT = 0x01;
+ /// Whether we're in a layout thread.
+ const LAYOUT = 0x02;
+
+ /// Whether we're in a script worker thread (actual web workers), or in
+ /// a layout worker thread.
+ const IN_WORKER = 0x0100;
+
+ /// Whether the current thread is going through a GC.
+ const IN_GC = 0x0200;
+ }
+}
+
+macro_rules! thread_types ( ( $( $fun:ident = $flag:path ; )* ) => (
+ impl ThreadState {
+ /// Whether the current thread is a worker thread.
+ pub fn is_worker(self) -> bool {
+ self.contains(ThreadState::IN_WORKER)
+ }
+
+ $(
+ #[allow(missing_docs)]
+ pub fn $fun(self) -> bool {
+ self.contains($flag)
+ }
+ )*
+ }
+));
+
+thread_types! {
+ is_script = ThreadState::SCRIPT;
+ is_layout = ThreadState::LAYOUT;
+}
+
+thread_local!(static STATE: RefCell<Option<ThreadState>> = RefCell::new(None));
+
+/// Initializes the current thread state.
+pub fn initialize(x: ThreadState) {
+ STATE.with(|ref k| {
+ if let Some(ref s) = *k.borrow() {
+ if x != *s {
+ panic!("Thread state already initialized as {:?}", s);
+ }
+ }
+ *k.borrow_mut() = Some(x);
+ });
+}
+
+/// Initializes the current thread as a layout worker thread.
+pub fn initialize_layout_worker_thread() {
+ initialize(ThreadState::LAYOUT | ThreadState::IN_WORKER);
+}
+
+/// Gets the current thread state.
+pub fn get() -> ThreadState {
+ let state = STATE.with(|ref k| {
+ match *k.borrow() {
+ None => ThreadState::empty(), // Unknown thread.
+ Some(s) => s,
+ }
+ });
+
+ state
+}
+
+/// Enters into a given temporary state. Panics if re-entring.
+pub fn enter(x: ThreadState) {
+ let state = get();
+ debug_assert!(!state.intersects(x));
+ STATE.with(|ref k| {
+ *k.borrow_mut() = Some(state | x);
+ })
+}
+
+/// Exits a given temporary state.
+pub fn exit(x: ThreadState) {
+ let state = get();
+ debug_assert!(state.contains(x));
+ STATE.with(|ref k| {
+ *k.borrow_mut() = Some(state & !x);
+ })
+}