aboutsummaryrefslogtreecommitdiffstats
path: root/components/style/thread_state.rs
diff options
context:
space:
mode:
authorMs2ger <Ms2ger@gmail.com>2016-08-22 16:05:00 +0200
committerMs2ger <Ms2ger@gmail.com>2016-08-22 16:08:56 +0200
commit307d1ced3cff2784c32f9523b74fd1c349481de6 (patch)
tree544e4fd99bf769879ccb9f320a65bb62be363ed7 /components/style/thread_state.rs
parent32a0493cde3339fbc86867d197f356741ee77c09 (diff)
downloadservo-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.rs105
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) { }
+}