Add a spawn_with! macro and clean up some spawns

This commit is contained in:
Keegan McAllister 2013-10-17 12:01:35 -07:00
parent 5b1fede394
commit 8bd9be7240
3 changed files with 37 additions and 54 deletions

View file

@ -17,6 +17,7 @@ use layout::incremental::{RestyleDamage, BubbleWidths};
use std::cast::transmute; use std::cast::transmute;
use std::cell::Cell; use std::cell::Cell;
use std::comm::{Port}; use std::comm::{Port};
use std::task;
use extra::arc::Arc; use extra::arc::Arc;
use geom::point::Point2D; use geom::point::Point2D;
use geom::rect::Rect; use geom::rect::Rect;
@ -75,25 +76,18 @@ impl LayoutTask {
img_cache_task: ImageCacheTask, img_cache_task: ImageCacheTask,
opts: Opts, opts: Opts,
profiler_chan: ProfilerChan) { profiler_chan: ProfilerChan) {
spawn_with!(task::task(), [port, constellation_chan, script_chan,
let port = Cell::new(port); render_chan, img_cache_task, profiler_chan], {
let constellation_chan = Cell::new(constellation_chan);
let script_chan = Cell::new(script_chan);
let render_chan = Cell::new(render_chan);
let img_cache_task = Cell::new(img_cache_task);
let profiler_chan = Cell::new(profiler_chan);
do spawn {
let mut layout = LayoutTask::new(id, let mut layout = LayoutTask::new(id,
port.take(), port,
constellation_chan.take(), constellation_chan,
script_chan.take(), script_chan,
render_chan.take(), render_chan,
img_cache_task.take(), img_cache_task,
&opts, &opts,
profiler_chan.take()); profiler_chan);
layout.start(); layout.start();
}; });
} }
fn new(id: PipelineId, fn new(id: PipelineId,

View file

@ -10,3 +10,15 @@ macro_rules! special_stream(
} }
); );
) )
// Spawn a task, capturing the listed variables in a way that avoids the
// move-from-closure error. This is sugar around the function spawn_with,
// taking care of building a tuple and a lambda.
//
// FIXME: Once cross-crate macros work, there are a few places outside of
// the main crate which could benefit from this macro.
macro_rules! spawn_with(
($task:expr, [ $($var:ident),+ ], $body:block) => (
do ($task).spawn_with(( $($var),+ , () )) |( $($var),+ , () )| $body
)
)

View file

@ -19,7 +19,6 @@ use servo_net::resource_task::ResourceTask;
use servo_util::time::ProfilerChan; use servo_util::time::ProfilerChan;
use geom::size::Size2D; use geom::size::Size2D;
use extra::future::Future; use extra::future::Future;
use std::cell::Cell;
use std::task; use std::task;
/// A uniquely-identifiable pipeline of script task, layout task, and render task. /// A uniquely-identifiable pipeline of script task, layout task, and render task.
@ -100,28 +99,18 @@ impl Pipeline {
script_chan.clone(), script_chan.clone(),
layout_chan.clone(), layout_chan.clone(),
render_chan.clone()); render_chan.clone());
let (port, chan) = stream::<task::TaskResult>();
let script_port = Cell::new(script_port); // Wrap task creation within a supervised task so that failure will
let resource_task = Cell::new(resource_task); // only tear down those tasks instead of ours.
let size = Cell::new(size); let failure_chan = constellation_chan.clone();
let render_port = Cell::new(render_port); let (task_port, task_chan) = stream::<task::TaskResult>();
let layout_port = Cell::new(layout_port); let mut supervised_task = task::task();
let constellation_chan_handler = Cell::new(constellation_chan.clone()); supervised_task.opts.notify_chan = Some(task_chan);
let constellation_chan = Cell::new(constellation_chan); supervised_task.supervised();
let image_cache_task = Cell::new(image_cache_task);
let profiler_chan = Cell::new(profiler_chan);
do Pipeline::spawn(chan) {
let script_port = script_port.take();
let resource_task = resource_task.take();
let size = size.take();
let render_port = render_port.take();
let layout_port = layout_port.take();
let constellation_chan = constellation_chan.take();
let image_cache_task = image_cache_task.take();
let profiler_chan = profiler_chan.take();
spawn_with!(supervised_task, [script_port, resource_task, size, render_port,
layout_port, constellation_chan, image_cache_task,
profiler_chan], {
ScriptTask::create(id, ScriptTask::create(id,
compositor_chan.clone(), compositor_chan.clone(),
layout_chan.clone(), layout_chan.clone(),
@ -147,32 +136,20 @@ impl Pipeline {
image_cache_task, image_cache_task,
opts.clone(), opts.clone(),
profiler_chan); profiler_chan);
}; });
do spawn { spawn_with!(task::task(), [failure_chan], {
match port.recv() { match task_port.recv() {
task::Success => (), task::Success => (),
task::Failure => { task::Failure => {
let constellation_chan = constellation_chan_handler.take(); failure_chan.send(FailureMsg(id, subpage_id));
constellation_chan.send(FailureMsg(id, subpage_id));
} }
} }
}; });
pipeline pipeline
} }
/// This function wraps the task creation within a supervised task
/// so that failure will only tear down those tasks instead of ours.
pub fn spawn(chan: Chan<task::TaskResult>, f: ~fn()) {
let mut task = task::task();
task.opts.notify_chan = Some(chan);
task.supervised();
do task.spawn {
f();
};
}
pub fn new(id: PipelineId, pub fn new(id: PipelineId,
subpage_id: Option<SubpageId>, subpage_id: Option<SubpageId>,
script_chan: ScriptChan, script_chan: ScriptChan,