Skip to content

Commit

Permalink
style: Make WorkQueue creation fallible.
Browse files Browse the repository at this point in the history
Fixes bug 1290205 in bugzilla.
  • Loading branch information
emilio committed Aug 26, 2016
1 parent 8a5e1b7 commit 4194ba0
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 15 deletions.
2 changes: 1 addition & 1 deletion components/layout_thread/lib.rs
Expand Up @@ -399,7 +399,7 @@ impl LayoutThread {
MediaType::Screen,
opts::get().initial_window_size.to_f32() * ScaleFactor::new(1.0));
let parallel_traversal = if layout_threads != 1 {
Some(WorkQueue::new("LayoutWorker", thread_state::LAYOUT, layout_threads))
WorkQueue::new("LayoutWorker", thread_state::LAYOUT, layout_threads).ok()
} else {
None
};
Expand Down
40 changes: 31 additions & 9 deletions components/style/workqueue.rs
Expand Up @@ -18,8 +18,8 @@ use deque::{self, Abort, Data, Empty, Stealer, Worker};
use rand::{Rng, XorShiftRng, weak_rng};
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::mpsc::{Receiver, Sender, channel};
use std::thread;
use thread_state;
use util::thread::spawn_named;

/// A unit of work.
///
Expand Down Expand Up @@ -244,10 +244,11 @@ impl<QueueData: Sync, WorkData: Send> WorkQueue<QueueData, WorkData> {
/// it.
pub fn new(thread_name: &'static str,
state: thread_state::ThreadState,
thread_count: usize) -> WorkQueue<QueueData, WorkData> {
thread_count: usize) -> Result<WorkQueue<QueueData, WorkData>, ()> {
// Set up data structures.
let (supervisor_chan, supervisor_port) = channel();
let (mut infos, mut threads) = (vec!(), vec!());
let mut infos = Vec::with_capacity(thread_count);
let mut threads = Vec::with_capacity(thread_count);
for i in 0..thread_count {
let (worker_chan, worker_port) = channel();
let (worker, thief) = deque::new();
Expand Down Expand Up @@ -276,21 +277,42 @@ impl<QueueData: Sync, WorkData: Send> WorkQueue<QueueData, WorkData> {
}

// Spawn threads.
let mut thread_handles = vec![];
for (i, thread) in threads.into_iter().enumerate() {
spawn_named(
format!("{} worker {}/{}", thread_name, i + 1, thread_count),
move || {
let handle = thread::Builder::new()
.name(format!("{} worker {}/{}", thread_name, i + 1, thread_count))
.spawn(move || {
thread_state::initialize(state | thread_state::IN_WORKER);
let mut thread = thread;
thread.start()
})
});
match handle {
Ok(handle) => {
thread_handles.push(handle);
}
Err(err) => {
warn!("Failed spawning thread: {:?}", err);
break;
}
}
}

if thread_handles.len() != thread_count {
// At least one worker thread failed to be created, just close the
// rest of them, and return an error.
for (i, handle) in thread_handles.into_iter().enumerate() {
let _ = infos[i].chan.send(WorkerMsg::Exit);
let _ = handle.join();
}

return Err(());
}

WorkQueue {
Ok(WorkQueue {
workers: infos,
port: supervisor_port,
work_count: 0,
}
})
}

/// Enqueues a block into the work queue.
Expand Down
12 changes: 9 additions & 3 deletions ports/geckolib/data.rs
Expand Up @@ -38,7 +38,7 @@ pub struct PerDocumentStyleData {
pub expired_animations: Arc<RwLock<HashMap<OpaqueNode, Vec<Animation>>>>,

// FIXME(bholley): This shouldn't be per-document.
pub work_queue: WorkQueue<SharedStyleContext, WorkQueueData>,
pub work_queue: Option<WorkQueue<SharedStyleContext, WorkQueueData>>,

pub num_threads: usize,
}
Expand Down Expand Up @@ -68,7 +68,11 @@ impl PerDocumentStyleData {
new_animations_receiver: new_anims_receiver,
running_animations: Arc::new(RwLock::new(HashMap::new())),
expired_animations: Arc::new(RwLock::new(HashMap::new())),
work_queue: WorkQueue::new("StyleWorker", thread_state::LAYOUT, *NUM_THREADS),
work_queue: if *NUM_THREADS <= 1 {
None
} else {
WorkQueue::new("StyleWorker", thread_state::LAYOUT, *NUM_THREADS).ok()
},
num_threads: *NUM_THREADS,
}
}
Expand All @@ -91,6 +95,8 @@ impl PerDocumentStyleData {

impl Drop for PerDocumentStyleData {
fn drop(&mut self) {
self.work_queue.shutdown();
if let Some(ref mut queue) = self.work_queue {
queue.shutdown();
}
}
}
4 changes: 2 additions & 2 deletions ports/geckolib/glue.rs
Expand Up @@ -103,11 +103,11 @@ fn restyle_subtree(node: GeckoNode, raw_data: *mut RawServoStyleSet) {

// We ensure this is true before calling Servo_RestyleSubtree()
debug_assert!(node.is_dirty() || node.has_dirty_descendants());
if per_doc_data.num_threads == 1 {
if per_doc_data.num_threads == 1 || per_doc_data.work_queue.is_none() {
sequential::traverse_dom::<GeckoNode, RecalcStyleOnly>(node, &shared_style_context);
} else {
parallel::traverse_dom::<GeckoNode, RecalcStyleOnly>(node, &shared_style_context,
&mut per_doc_data.work_queue);
per_doc_data.work_queue.as_mut().unwrap());
}
}

Expand Down

0 comments on commit 4194ba0

Please sign in to comment.