diff options
Diffstat (limited to '')
-rw-r--r-- | servo/components/style/thread_state.rs | 98 |
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..e07a567fe7 --- /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, Debug, 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); + }) +} |