diff --git a/src/libcore/task/mod.rs b/src/libcore/task/mod.rs index fd695c16ea7..24889800175 100644 --- a/src/libcore/task/mod.rs +++ b/src/libcore/task/mod.rs @@ -156,7 +156,7 @@ pub struct SchedOpts { pub struct TaskOpts { linked: bool, supervised: bool, - mut notify_chan: Option>, + notify_chan: Option>, sched: SchedOpts } @@ -176,9 +176,9 @@ pub struct TaskOpts { // FIXME (#3724): Replace the 'consumed' bit with move mode on self pub struct TaskBuilder { opts: TaskOpts, - mut gen_body: Option<~fn(v: ~fn()) -> ~fn()>, + gen_body: Option<~fn(v: ~fn()) -> ~fn()>, can_not_copy: Option, - mut consumed: bool, + consumed: bool, } /** @@ -191,13 +191,13 @@ pub fn task() -> TaskBuilder { opts: default_task_opts(), gen_body: None, can_not_copy: None, - mut consumed: false, + consumed: false, } } #[doc(hidden)] // FIXME #3538 priv impl TaskBuilder { - fn consume(&self) -> TaskBuilder { + fn consume(&mut self) -> TaskBuilder { if self.consumed { fail!(~"Cannot copy a task_builder"); // Fake move mode on self } @@ -219,57 +219,23 @@ priv impl TaskBuilder { } pub impl TaskBuilder { - /** - * Decouple the child task's failure from the parent's. If either fails, - * the other will not be killed. - */ - fn unlinked(&self) -> TaskBuilder { - let notify_chan = replace(&mut self.opts.notify_chan, None); - TaskBuilder { - opts: TaskOpts { - linked: false, - supervised: self.opts.supervised, - notify_chan: notify_chan, - sched: self.opts.sched - }, - can_not_copy: None, - .. self.consume() - } + /// Decouple the child task's failure from the parent's. If either fails, + /// the other will not be killed. + fn unlinked(&mut self) { + self.opts.linked = false; } - /** - * Unidirectionally link the child task's failure with the parent's. The - * child's failure will not kill the parent, but the parent's will kill - * the child. - */ - fn supervised(&self) -> TaskBuilder { - let notify_chan = replace(&mut self.opts.notify_chan, None); - TaskBuilder { - opts: TaskOpts { - linked: false, - supervised: true, - notify_chan: notify_chan, - sched: self.opts.sched - }, - can_not_copy: None, - .. self.consume() - } + + /// Unidirectionally link the child task's failure with the parent's. The + /// child's failure will not kill the parent, but the parent's will kill + /// the child. + fn supervised(&mut self) { + self.opts.supervised = true; } - /** - * Link the child task's and parent task's failures. If either fails, the - * other will be killed. - */ - fn linked(&self) -> TaskBuilder { - let notify_chan = replace(&mut self.opts.notify_chan, None); - TaskBuilder { - opts: TaskOpts { - linked: true, - supervised: false, - notify_chan: notify_chan, - sched: self.opts.sched - }, - can_not_copy: None, - .. self.consume() - } + + /// Link the child task's and parent task's failures. If either fails, the + /// other will be killed. + fn linked(&mut self) { + self.opts.linked = true; } /** @@ -289,7 +255,7 @@ pub impl TaskBuilder { * # Failure * Fails if a future_result was already set for this task. */ - fn future_result(&self, blk: &fn(v: Port)) -> TaskBuilder { + fn future_result(&mut self, blk: &fn(v: Port)) { // FIXME (#3725): Once linked failure and notification are // handled in the library, I can imagine implementing this by just // registering an arbitrary number of task::on_exit handlers and @@ -305,30 +271,12 @@ pub impl TaskBuilder { blk(notify_pipe_po); // Reconfigure self to use a notify channel. - TaskBuilder { - opts: TaskOpts { - linked: self.opts.linked, - supervised: self.opts.supervised, - notify_chan: Some(notify_pipe_ch), - sched: self.opts.sched - }, - can_not_copy: None, - .. self.consume() - } + self.opts.notify_chan = Some(notify_pipe_ch); } + /// Configure a custom scheduler mode for the task. - fn sched_mode(&self, mode: SchedMode) -> TaskBuilder { - let notify_chan = replace(&mut self.opts.notify_chan, None); - TaskBuilder { - opts: TaskOpts { - linked: self.opts.linked, - supervised: self.opts.supervised, - notify_chan: notify_chan, - sched: SchedOpts { mode: mode, foreign_stack_size: None} - }, - can_not_copy: None, - .. self.consume() - } + fn sched_mode(&mut self, mode: SchedMode) { + self.opts.sched.mode = mode; } /** @@ -343,7 +291,7 @@ pub impl TaskBuilder { * generator by applying the task body which results from the * existing body generator to the new body generator. */ - fn add_wrapper(&self, wrapper: ~fn(v: ~fn()) -> ~fn()) -> TaskBuilder { + fn add_wrapper(&mut self, wrapper: ~fn(v: ~fn()) -> ~fn()) { let prev_gen_body = replace(&mut self.gen_body, None); let prev_gen_body = match prev_gen_body { Some(gen) => gen, @@ -360,18 +308,7 @@ pub impl TaskBuilder { }; f }; - let notify_chan = replace(&mut self.opts.notify_chan, None); - TaskBuilder { - opts: TaskOpts { - linked: self.opts.linked, - supervised: self.opts.supervised, - notify_chan: notify_chan, - sched: self.opts.sched - }, - gen_body: Some(next_gen_body), - can_not_copy: None, - .. self.consume() - } + self.gen_body = Some(next_gen_body); } /** @@ -386,7 +323,7 @@ pub impl TaskBuilder { * When spawning into a new scheduler, the number of threads requested * must be greater than zero. */ - fn spawn(&self, f: ~fn()) { + fn spawn(&mut self, f: ~fn()) { let gen_body = replace(&mut self.gen_body, None); let notify_chan = replace(&mut self.opts.notify_chan, None); let x = self.consume(); @@ -406,8 +343,9 @@ pub impl TaskBuilder { }; spawn::spawn_raw(opts, f); } + /// Runs a task, while transfering ownership of one argument to the child. - fn spawn_with(&self, arg: A, f: ~fn(v: A)) { + fn spawn_with(&mut self, arg: A, f: ~fn(v: A)) { let arg = Cell(arg); do self.spawn { f(arg.take()); @@ -427,16 +365,16 @@ pub impl TaskBuilder { * # Failure * Fails if a future_result was already set for this task. */ - fn try(&self, f: ~fn() -> T) -> Result { + fn try(&mut self, f: ~fn() -> T) -> Result { let (po, ch) = stream::(); let mut result = None; - let fr_task_builder = self.future_result(|+r| { - result = Some(r); - }); - do fr_task_builder.spawn || { + self.future_result(|+r| { result = Some(r); }); + + do self.spawn { ch.send(f()); } + match result.unwrap().recv() { Success => result::Ok(po.recv()), Failure => result::Err(()) @@ -468,26 +406,23 @@ pub fn default_task_opts() -> TaskOpts { /* Spawn convenience functions */ +/// Creates and executes a new child task +/// +/// Sets up a new task with its own call stack and schedules it to run +/// the provided unique closure. +/// +/// This function is equivalent to `task().spawn(f)`. pub fn spawn(f: ~fn()) { - /*! - * Creates and executes a new child task - * - * Sets up a new task with its own call stack and schedules it to run - * the provided unique closure. - * - * This function is equivalent to `task().spawn(f)`. - */ - - task().spawn(f) + let mut task = task(); + task.spawn(f) } +/// Creates a child task unlinked from the current one. If either this +/// task or the child task fails, the other will not be killed. pub fn spawn_unlinked(f: ~fn()) { - /*! - * Creates a child task unlinked from the current one. If either this - * task or the child task fails, the other will not be killed. - */ - - task().unlinked().spawn(f) + let mut task = task(); + task.unlinked(); + task.spawn(f) } pub fn spawn_supervised(f: ~fn()) { @@ -497,7 +432,9 @@ pub fn spawn_supervised(f: ~fn()) { * the child will be killed. */ - task().supervised().spawn(f) + let mut task = task(); + task.supervised(); + task.spawn(f) } pub fn spawn_with(arg: A, f: ~fn(v: A)) { @@ -511,7 +448,8 @@ pub fn spawn_with(arg: A, f: ~fn(v: A)) { * This function is equivalent to `task().spawn_with(arg, f)`. */ - task().spawn_with(arg, f) + let mut task = task(); + task.spawn_with(arg, f) } pub fn spawn_sched(mode: SchedMode, f: ~fn()) { @@ -527,7 +465,9 @@ pub fn spawn_sched(mode: SchedMode, f: ~fn()) { * greater than zero. */ - task().sched_mode(mode).spawn(f) + let mut task = task(); + task.sched_mode(mode); + task.spawn(f) } pub fn try(f: ~fn() -> T) -> Result { @@ -538,7 +478,9 @@ pub fn try(f: ~fn() -> T) -> Result { * This is equivalent to task().supervised().try. */ - task().supervised().try(f) + let mut task = task(); + task.supervised(); + task.try(f) } @@ -822,7 +764,7 @@ fn test_run_basic() { #[cfg(test)] struct Wrapper { - mut f: Option> + f: Option> } #[test] diff --git a/src/libcore/task/spawn.rs b/src/libcore/task/spawn.rs index 63959edb427..19c417dfdfc 100644 --- a/src/libcore/task/spawn.rs +++ b/src/libcore/task/spawn.rs @@ -580,7 +580,7 @@ fn spawn_raw_newsched(_opts: TaskOpts, f: ~fn()) { sched.schedule_new_task(task); } -fn spawn_raw_oldsched(opts: TaskOpts, f: ~fn()) { +fn spawn_raw_oldsched(mut opts: TaskOpts, f: ~fn()) { let (child_tg, ancestors, is_main) = gen_child_taskgroup(opts.linked, opts.supervised); diff --git a/src/libcore/unstable/at_exit.rs b/src/libcore/unstable/at_exit.rs index c9cd2f61e5c..39c930d415f 100644 --- a/src/libcore/unstable/at_exit.rs +++ b/src/libcore/unstable/at_exit.rs @@ -70,7 +70,9 @@ fn exit_runner(exit_fns: *ExitFunctions) { while !exit_fns_vec.is_empty() { match exit_fns_vec.pop() { ~f => { - task::task().supervised().spawn(f); + let mut task = task::task(); + task.supervised(); + task.spawn(f); } } } diff --git a/src/libcore/unstable/weak_task.rs b/src/libcore/unstable/weak_task.rs index 6edbdcb51b0..381083e6031 100644 --- a/src/libcore/unstable/weak_task.rs +++ b/src/libcore/unstable/weak_task.rs @@ -72,7 +72,9 @@ fn create_global_service() -> ~WeakTaskService { let chan = SharedChan::new(chan); let chan_clone = chan.clone(); - do task().unlinked().spawn { + let mut task = task(); + task.unlinked(); + do task.spawn { debug!("running global weak task service"); let port = Cell(port.take()); do (|| { diff --git a/src/libstd/task_pool.rs b/src/libstd/task_pool.rs index 661247df1c1..0c52e1ff80e 100644 --- a/src/libstd/task_pool.rs +++ b/src/libstd/task_pool.rs @@ -70,7 +70,9 @@ pub impl TaskPool { task::spawn(task_body); } Some(sched_mode) => { - task::task().sched_mode(sched_mode).spawn(task_body); + let mut task = task::task(); + task.sched_mode(sched_mode); + task.spawn(task_body); } } diff --git a/src/libstd/test.rs b/src/libstd/test.rs index 7c0673a280b..b3523b8ad80 100644 --- a/src/libstd/test.rs +++ b/src/libstd/test.rs @@ -556,9 +556,12 @@ pub fn run_test(force_ignore: bool, let testfn_cell = ::core::cell::Cell(testfn); do task::spawn { let mut result_future = None; // task::future_result(builder); - task::task().unlinked().future_result(|+r| { - result_future = Some(r); - }).spawn(testfn_cell.take()); + + let mut task = task::task(); + task.unlinked(); + task.future_result(|+r| { result_future = Some(r) }); + task.spawn(testfn_cell.take()); + let task_result = result_future.unwrap().recv(); let test_result = calc_result(&desc, task_result == task::Success); diff --git a/src/libstd/uv_global_loop.rs b/src/libstd/uv_global_loop.rs index e49cee434f8..e1b7eb61505 100644 --- a/src/libstd/uv_global_loop.rs +++ b/src/libstd/uv_global_loop.rs @@ -62,7 +62,9 @@ fn get_monitor_task_gl() -> IoTask { } }; if installed { - do task().unlinked().spawn() { + let mut task = task(); + task.unlinked(); + do task.spawn { unsafe { debug!("global monitor task starting"); // As a weak task the runtime will notify us @@ -88,7 +90,9 @@ fn get_monitor_task_gl() -> IoTask { } fn spawn_loop() -> IoTask { - let builder = do task().add_wrapper |task_body| { + let mut builder = task(); + + do builder.add_wrapper |task_body| { let result: ~fn() = || { // The I/O loop task also needs to be weak so it doesn't keep // the runtime alive @@ -107,7 +111,8 @@ fn spawn_loop() -> IoTask { }; result }; - let builder = builder.unlinked(); + + builder.unlinked(); spawn_iotask(builder) } diff --git a/src/libstd/uv_iotask.rs b/src/libstd/uv_iotask.rs index e19010e8552..83e95a6e199 100644 --- a/src/libstd/uv_iotask.rs +++ b/src/libstd/uv_iotask.rs @@ -36,11 +36,11 @@ impl Clone for IoTask { } } -pub fn spawn_iotask(task: task::TaskBuilder) -> IoTask { - +pub fn spawn_iotask(mut task: task::TaskBuilder) -> IoTask { let (iotask_port, iotask_chan) = stream(); - do task.sched_mode(task::SingleThreaded).spawn { + task.sched_mode(task::SingleThreaded); + do task.spawn { debug!("entering libuv task"); run_loop(&iotask_chan); debug!("libuv task exiting");