diff options
author | Ms2ger <Ms2ger@gmail.com> | 2016-08-22 16:05:00 +0200 |
---|---|---|
committer | Ms2ger <Ms2ger@gmail.com> | 2016-08-22 16:08:56 +0200 |
commit | 307d1ced3cff2784c32f9523b74fd1c349481de6 (patch) | |
tree | 544e4fd99bf769879ccb9f320a65bb62be363ed7 /components/style/thread_state.rs | |
parent | 32a0493cde3339fbc86867d197f356741ee77c09 (diff) | |
download | servo-307d1ced3cff2784c32f9523b74fd1c349481de6.tar.gz servo-307d1ced3cff2784c32f9523b74fd1c349481de6.zip |
Move thread_state to style.
Diffstat (limited to 'components/style/thread_state.rs')
-rw-r--r-- | components/style/thread_state.rs | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/components/style/thread_state.rs b/components/style/thread_state.rs new file mode 100644 index 00000000000..25e77ecbb45 --- /dev/null +++ b/components/style/thread_state.rs @@ -0,0 +1,105 @@ +/* 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 http://mozilla.org/MPL/2.0/. */ + +//! Supports dynamic assertions in debug builds about what sort of thread is +//! running and what state it's in. +//! +//! In release builds, `get` returns 0. All of the other functions inline +//! away to nothing. + +pub use self::imp::{enter, exit, get, initialize}; + +bitflags! { + pub flags ThreadState: u32 { + const SCRIPT = 0x01, + const LAYOUT = 0x02, + const PAINT = 0x04, + + const IN_WORKER = 0x0100, + const IN_GC = 0x0200, + const IN_HTML_PARSER = 0x0400, + } +} + +macro_rules! thread_types ( ( $( $fun:ident = $flag:ident ; )* ) => ( + impl ThreadState { + $( + #[cfg(debug_assertions)] + pub fn $fun(self) -> bool { + self.contains($flag) + } + #[cfg(not(debug_assertions))] + pub fn $fun(self) -> bool { + true + } + )* + } + + #[cfg(debug_assertions)] + static TYPES: &'static [ThreadState] + = &[ $( $flag ),* ]; +)); + +thread_types! { + is_script = SCRIPT; + is_layout = LAYOUT; + is_paint = PAINT; +} + +#[cfg(debug_assertions)] +mod imp { + use std::cell::RefCell; + use super::{TYPES, ThreadState}; + + thread_local!(static STATE: RefCell<Option<ThreadState>> = RefCell::new(None)); + + pub fn initialize(x: ThreadState) { + STATE.with(|ref k| { + match *k.borrow() { + Some(s) => panic!("Thread state already initialized as {:?}", s), + None => () + }; + *k.borrow_mut() = Some(x); + }); + get(); // check the assertion below + } + + pub fn get() -> ThreadState { + let state = STATE.with(|ref k| { + match *k.borrow() { + None => panic!("Thread state not initialized"), + Some(s) => s, + } + }); + + // Exactly one of the thread type flags should be set. + assert_eq!(1, TYPES.iter().filter(|&&ty| state.contains(ty)).count()); + state + } + + pub fn enter(x: ThreadState) { + let state = get(); + assert!(!state.intersects(x)); + STATE.with(|ref k| { + *k.borrow_mut() = Some(state | x); + }) + } + + pub fn exit(x: ThreadState) { + let state = get(); + assert!(state.contains(x)); + STATE.with(|ref k| { + *k.borrow_mut() = Some(state & !x); + }) + } +} + +#[cfg(not(debug_assertions))] +mod imp { + use super::ThreadState; + #[inline(always)] pub fn initialize(_: ThreadState) { } + #[inline(always)] pub fn get() -> ThreadState { ThreadState::empty() } + #[inline(always)] pub fn enter(_: ThreadState) { } + #[inline(always)] pub fn exit(_: ThreadState) { } +} |