]> git.lizzy.rs Git - rust.git/commitdiff
(cleanup) Modernize taskgroup code for the new borrow-checker.
authorBen Blum <bblum@andrew.cmu.edu>
Mon, 15 Jul 2013 17:59:17 +0000 (13:59 -0400)
committerBen Blum <bblum@andrew.cmu.edu>
Sat, 20 Jul 2013 09:08:58 +0000 (05:08 -0400)
src/libstd/task/spawn.rs

index 303028b30a27d4c223c3fe0d9077a89c4491a6b9..ea7be96b3a165815292c9a1fb4a4c4a76e7def40 100644 (file)
@@ -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 coalesce(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 coalesce(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 iterate(ancestors:       &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 iterate(ancestors:       &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 iterate(ancestors:       &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 iterate(ancestors:       &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 @@ fn with_task_handle_and_failing(blk: &fn(TaskHandle, bool)) {
         }
     }
 
-    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 @@ fn with_my_taskgroup<U>(blk: &fn(&mut TCB) -> U) -> U {
                             // 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 @@ fn with_my_taskgroup<U>(blk: &fn(&mut TCB) -> U) -> U {
                         }));
                         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 @@ fn with_my_taskgroup<U>(blk: &fn(&mut TCB) -> U) -> U {
 
 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);