diff options
| author | Ben Blum <bblum@andrew.cmu.edu> | 2013-07-15 13:59:17 -0400 |
|---|---|---|
| committer | Ben Blum <bblum@andrew.cmu.edu> | 2013-07-20 05:08:58 -0400 |
| commit | 87bbcb579a170f4d2c36df4370703075c81b0b5d (patch) | |
| tree | 229059be4eac9373f431358e3135c7651212b6cd /src/libstd/task | |
| parent | 9bbec651dfff68c93d7213fceadecc21c324b0cb (diff) | |
| download | rust-87bbcb579a170f4d2c36df4370703075c81b0b5d.tar.gz rust-87bbcb579a170f4d2c36df4370703075c81b0b5d.zip | |
(cleanup) Modernize taskgroup code for the new borrow-checker.
Diffstat (limited to 'src/libstd/task')
| -rw-r--r-- | src/libstd/task/spawn.rs | 81 |
1 files changed, 20 insertions, 61 deletions
diff --git a/src/libstd/task/spawn.rs b/src/libstd/task/spawn.rs index 303028b30a2..ea7be96b3a1 100644 --- a/src/libstd/task/spawn.rs +++ b/src/libstd/task/spawn.rs @@ -178,8 +178,8 @@ struct AncestorNode { // approach the tail of the list. // FIXME(#3068): Make the generation counter togglable with #[cfg(debug)]. generation: uint, - // Should really be a non-option. This way appeases borrowck. - parent_group: Option<TaskGroupArc>, + // Handle to the tasks in the group of the current generation. + parent_group: TaskGroupArc, // Recursive rest of the list. ancestors: AncestorList, } @@ -221,18 +221,13 @@ fn each_ancestor(list: &mut AncestorList, bail_blk: &fn(TaskGroupInner), forward_blk: &fn(TaskGroupInner) -> bool, last_generation: uint) -> bool { - // Need to swap the list out to use it, to appease borrowck. - let tmp_list = util::replace(&mut *list, AncestorList(None)); let (coalesce_this, early_break) = - iterate(&tmp_list, bail_blk, forward_blk, last_generation); + iterate(list, bail_blk, forward_blk, last_generation); // What should our next ancestor end up being? if coalesce_this.is_some() { // Needed coalesce. Our next ancestor becomes our old // ancestor's next ancestor. ("next = old_next->next;") *list = coalesce_this.unwrap(); - } else { - // No coalesce; restore from tmp. ("next = old_next;") - *list = tmp_list; } return early_break; } @@ -245,7 +240,7 @@ fn each_ancestor(list: &mut AncestorList, // bool: // True if the supplied block did 'break', here or in any recursive // calls. If so, must call the unwinder on all previous nodes. - fn iterate(ancestors: &AncestorList, + fn iterate(ancestors: &mut AncestorList, bail_blk: &fn(TaskGroupInner), forward_blk: &fn(TaskGroupInner) -> bool, last_generation: uint) @@ -263,7 +258,7 @@ fn each_ancestor(list: &mut AncestorList, // The map defaults to None, because if ancestors is None, we're at // the end of the list, which doesn't make sense to coalesce. - return do (**ancestors).map_default((None,false)) |ancestor_arc| { + do ancestors.map_default((None,false)) |ancestor_arc| { // NB: Takes a lock! (this ancestor node) do access_ancestors(ancestor_arc) |nobe| { // Argh, but we couldn't give it to coalesce() otherwise. @@ -276,7 +271,7 @@ fn each_ancestor(list: &mut AncestorList, let mut nobe_is_dead = false; let do_continue = // NB: Takes a lock! (this ancestor node's parent group) - do with_parent_tg(&mut nobe.parent_group) |tg_opt| { + do access_group(&nobe.parent_group) |tg_opt| { // Decide whether this group is dead. Note that the // group being *dead* is disjoint from it *failing*. nobe_is_dead = match *tg_opt { @@ -305,7 +300,7 @@ fn each_ancestor(list: &mut AncestorList, * Step 3: Maybe unwind; compute return info for our caller. *##########################################################*/ if need_unwind && !nobe_is_dead { - do with_parent_tg(&mut nobe.parent_group) |tg_opt| { + do access_group(&nobe.parent_group) |tg_opt| { bail_blk(tg_opt) } } @@ -321,16 +316,6 @@ fn each_ancestor(list: &mut AncestorList, (None, need_unwind) } } - }; - - // Wrapper around exclusive::with that appeases borrowck. - fn with_parent_tg<U>(parent_group: &mut Option<TaskGroupArc>, - blk: &fn(TaskGroupInner) -> U) -> U { - // If this trips, more likely the problem is 'blk' failed inside. - let tmp_arc = parent_group.take_unwrap(); - let result = do access_group(&tmp_arc) |tg_opt| { blk(tg_opt) }; - *parent_group = Some(tmp_arc); - result } } } @@ -544,7 +529,7 @@ impl RuntimeGlue { } } - fn with_my_taskgroup<U>(blk: &fn(&mut TCB) -> U) -> U { + fn with_my_taskgroup<U>(blk: &fn(&TCB) -> U) -> U { match context() { OldTaskContext => unsafe { let me = rt::rust_get_task(); @@ -561,9 +546,9 @@ impl RuntimeGlue { // Main task/group has no ancestors, no notifier, etc. let group = @@mut TCB(tasks, AncestorList(None), true, None); local_set(OldHandle(me), taskgroup_key(), group); - blk(&mut **group) + blk(&**group) } - Some(&group) => blk(&mut **group) + Some(&group) => blk(&**group) } } }, @@ -583,9 +568,9 @@ impl RuntimeGlue { })); let group = TCB(tasks, AncestorList(None), true, None); (*me).taskgroup = Some(group); - (*me).taskgroup.get_mut_ref() + (*me).taskgroup.get_ref() } - Some(ref mut group) => group, + Some(ref group) => group, }) }, SchedulerContext | GlobalContext => rtabort!("spawning in bad context"), @@ -595,14 +580,13 @@ impl RuntimeGlue { fn gen_child_taskgroup(linked: bool, supervised: bool) -> (TaskGroupArc, AncestorList, bool) { - return do RuntimeGlue::with_my_taskgroup |spawner_group| { + do RuntimeGlue::with_my_taskgroup |spawner_group| { + let ancestors = AncestorList(spawner_group.ancestors.map(|x| x.clone())); if linked { // Child is in the same group as spawner. - let g = spawner_group.tasks.clone(); // Child's ancestors are spawner's ancestors. - let a = share_ancestors(&mut spawner_group.ancestors); // Propagate main-ness. - (g, a, spawner_group.is_main) + (spawner_group.tasks.clone(), ancestors, spawner_group.is_main) } else { // Child is in a separate group from spawner. let g = exclusive(Some(TaskGroupData { @@ -610,25 +594,23 @@ fn gen_child_taskgroup(linked: bool, supervised: bool) descendants: new_taskset(), })); let a = if supervised { - // Child's ancestors start with the spawner. - let old_ancestors = - share_ancestors(&mut spawner_group.ancestors); // FIXME(#3068) - The generation counter is only used for a // debug assertion, but initialising it requires locking a // mutex. Hence it should be enabled only in debug builds. let new_generation = - match *old_ancestors { + match *ancestors { Some(ref arc) => { access_ancestors(arc, |a| a.generation+1) } None => 0 // the actual value doesn't really matter. }; assert!(new_generation < uint::max_value); + // Child's ancestors start with the spawner. // Build a new node in the ancestor list. AncestorList(Some(exclusive(AncestorNode { generation: new_generation, - parent_group: Some(spawner_group.tasks.clone()), - ancestors: old_ancestors, + parent_group: spawner_group.tasks.clone(), + ancestors: ancestors, }))) } else { // Child has no ancestors. @@ -636,23 +618,6 @@ fn gen_child_taskgroup(linked: bool, supervised: bool) }; (g, a, false) } - }; - - fn share_ancestors(ancestors: &mut AncestorList) -> AncestorList { - // Appease the borrow-checker. Really this wants to be written as: - // match ancestors - // Some(ancestor_arc) { ancestor_list(Some(ancestor_arc.clone())) } - // None { ancestor_list(None) } - let tmp = util::replace(&mut **ancestors, None); - if tmp.is_some() { - let ancestor_arc = tmp.unwrap(); - let result = ancestor_arc.clone(); - error!("cloned ancestors"); - **ancestors = Some(ancestor_arc); - AncestorList(Some(result)) - } else { - AncestorList(None) - } } } @@ -754,14 +719,8 @@ fn spawn_raw_oldsched(mut opts: TaskOpts, f: ~fn()) { }; assert!(!new_task.is_null()); // Getting killed after here would leak the task. - let notify_chan = if opts.notify_chan.is_none() { - None - } else { - Some(opts.notify_chan.take_unwrap()) - }; - let child_wrapper = make_child_wrapper(new_task, child_tg, - ancestors, is_main, notify_chan, f); + ancestors, is_main, opts.notify_chan.take(), f); let closure = cast::transmute(&child_wrapper); |
