diff --git a/src/components/main/layout/layout_task.rs b/src/components/main/layout/layout_task.rs index b91e22369f0..1feb7338c62 100644 --- a/src/components/main/layout/layout_task.rs +++ b/src/components/main/layout/layout_task.rs @@ -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, diff --git a/src/components/main/macros.rs b/src/components/main/macros.rs index 9f364c48f74..144d57d40c4 100644 --- a/src/components/main/macros.rs +++ b/src/components/main/macros.rs @@ -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 + ) +) diff --git a/src/components/main/pipeline.rs b/src/components/main/pipeline.rs index 12b301a4c68..da9848c0181 100644 --- a/src/components/main/pipeline.rs +++ b/src/components/main/pipeline.rs @@ -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::(); - - 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::(); + 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, 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, script_chan: ScriptChan,