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::cell::Cell;
use std::comm::{Port};
use std::task;
use extra::arc::Arc;
use geom::point::Point2D;
use geom::rect::Rect;
@ -75,25 +76,18 @@ impl LayoutTask {
img_cache_task: ImageCacheTask,
opts: Opts,
profiler_chan: ProfilerChan) {
let port = Cell::new(port);
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 {
spawn_with!(task::task(), [port, constellation_chan, script_chan,
render_chan, img_cache_task, profiler_chan], {
let mut layout = LayoutTask::new(id,
port.take(),
constellation_chan.take(),
script_chan.take(),
render_chan.take(),
img_cache_task.take(),
port,
constellation_chan,
script_chan,
render_chan,
img_cache_task,
&opts,
profiler_chan.take());
profiler_chan);
layout.start();
};
});
}
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 geom::size::Size2D;
use extra::future::Future;
use std::cell::Cell;
use std::task;
/// A uniquely-identifiable pipeline of script task, layout task, and render task.
@ -100,28 +99,18 @@ impl Pipeline {
script_chan.clone(),
layout_chan.clone(),
render_chan.clone());
let (port, chan) = stream::<task::TaskResult>();
let script_port = Cell::new(script_port);
let resource_task = Cell::new(resource_task);
let size = Cell::new(size);
let render_port = Cell::new(render_port);
let layout_port = Cell::new(layout_port);
let constellation_chan_handler = Cell::new(constellation_chan.clone());
let constellation_chan = Cell::new(constellation_chan);
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();
// Wrap task creation within a supervised task so that failure will
// only tear down those tasks instead of ours.
let failure_chan = constellation_chan.clone();
let (task_port, task_chan) = stream::<task::TaskResult>();
let mut supervised_task = task::task();
supervised_task.opts.notify_chan = Some(task_chan);
supervised_task.supervised();
spawn_with!(supervised_task, [script_port, resource_task, size, render_port,
layout_port, constellation_chan, image_cache_task,
profiler_chan], {
ScriptTask::create(id,
compositor_chan.clone(),
layout_chan.clone(),
@ -147,32 +136,20 @@ impl Pipeline {
image_cache_task,
opts.clone(),
profiler_chan);
};
});
do spawn {
match port.recv() {
spawn_with!(task::task(), [failure_chan], {
match task_port.recv() {
task::Success => (),
task::Failure => {
let constellation_chan = constellation_chan_handler.take();
constellation_chan.send(FailureMsg(id, subpage_id));
failure_chan.send(FailureMsg(id, subpage_id));
}
}
};
});
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,
subpage_id: Option<SubpageId>,
script_chan: ScriptChan,