gecko-dev/servo/components/style/thread_state.rs
Emilio Cobos Álvarez fbd6dc3fd6 servo: Merge #13641 - Use rayon to drive parallel layout and styling (from emilio:rayon-style); r=pcwalton
<!-- Please describe your changes on the following line: -->

The current work queue had a really annoying constraint: The size of the node had to be the size of the work unit data.

This makes it impractical for the new restyling model where we plan to pass down a bunch of data.

Rayon by default makes you wait for the result of the work unit, which makes it impractical for the current model (it's mostly sequential).

I added an API to rayon that allows us to push work to the queue without waiting (https://github.com/nikomatsakis/rayon/pull/103).

This still needs some work (for example, we're loosing the memory reporting functionality), but I wanted feedback on this.

---

<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: -->
- [ ] `./mach build -d` does not report any errors
- [ ] `./mach test-tidy` does not report any errors
- [ ] These changes fix #__ (github issue number if applicable).

<!-- Either: -->
- [ ] There are tests for these changes OR
- [ ] These changes do not require tests because _____

<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->

Source-Repo: https://github.com/servo/servo
Source-Revision: 9467fbe26d25dfc633d5ab8973fe459d14eff9dc
2016-11-14 14:47:21 -06:00

111 lines
3.0 KiB
Rust

/* 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 {
pub fn is_worker(self) -> bool {
self.contains(IN_WORKER)
}
$(
#[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() {
// This is one of the layout threads, that use rayon.
None => super::LAYOUT | super::IN_WORKER,
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) { }
}