about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorEric Holk <eric.holk@gmail.com>2012-05-29 13:13:31 -0700
committerEric Holk <eric.holk@gmail.com>2012-05-30 12:03:51 -0700
commit6abddca18b432d37945bd2fda24bbc77fba970aa (patch)
tree4f1594fc99f30f49295027b73290eeccd5b7c961 /src/libstd
parentdca11e1f99bcb3b1e645625113d188c8b1b43f8d (diff)
downloadrust-6abddca18b432d37945bd2fda24bbc77fba970aa.tar.gz
rust-6abddca18b432d37945bd2fda24bbc77fba970aa.zip
Rewriting shared_arc to work around Issue #2444.
Sadly, this exposes another ICE when trying to use the new version with Graph500
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/arc.rs57
1 files changed, 42 insertions, 15 deletions
diff --git a/src/libstd/arc.rs b/src/libstd/arc.rs
index 067191a855b..2b76f7f3b03 100644
--- a/src/libstd/arc.rs
+++ b/src/libstd/arc.rs
@@ -76,34 +76,42 @@ fn clone<T: const>(rc: &arc<T>) -> arc<T> {
 
 // Convenience code for sharing arcs between tasks
 
-enum proto<T: send const> {
-    terminate,
-    shared_get(comm::chan<arc::arc<T>>)
-}
+type get_chan<T: const send> = chan<chan<arc<T>>>;
+
+// (terminate, get)
+type shared_arc<T: const send> = (shared_arc_res, get_chan<T>);
 
-resource shared_arc_res<T: send const>(c: comm::chan<proto<T>>) {
-    c.send(terminate);
+resource shared_arc_res(c: comm::chan<()>) {
+    c.send(());
 }
 
-fn shared_arc<T: send const>(-data: T) -> shared_arc_res<T> {
+fn shared_arc<T: send const>(-data: T) -> shared_arc<T> {
     let a = arc::arc(data);
-    let c = task::spawn_listener::<proto<T>>() {|p, move a|
+    let p = port();
+    let c = chan(p);
+    task::spawn() {|move a|
         let mut live = true;
+        let terminate = port();
+        let get = port();
+
+        c.send((chan(terminate), chan(get)));
+
         while live {
-            alt p.recv() {
-              terminate { live = false; }
-              shared_get(cc) {
-                cc.send(arc::clone(&a));
+            alt comm::select2(terminate, get) {
+              either::left(()) { live = false; }
+              either::right(cc) {
+                comm::send(cc, arc::clone(&a));
               }
             }
         }
     };
-    shared_arc_res(c)
+    let (terminate, get) = p.recv();
+    (shared_arc_res(terminate), get)
 }
 
-fn get_arc<T: send const>(c: comm::chan<proto<T>>) -> arc::arc<T> {
+fn get_arc<T: send const>(c: get_chan<T>) -> arc::arc<T> {
     let p = port();
-    c.send(shared_get(chan(p)));
+    c.send(chan(p));
     p.recv()
 }
 
@@ -136,4 +144,23 @@ mod tests {
 
         log(info, arc_v);
     }
+
+    #[test]
+    fn auto_share_arc() {
+        let v = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+        let (res, arc_c) = shared_arc(v);
+
+        let p = port();
+        let c = chan(p);
+
+        task::spawn() {||
+            let arc_v = get_arc(arc_c);
+            let v = *get(&arc_v);
+            assert v[2] == 3;
+
+            c.send(());
+        };
+
+        assert p.recv() == ();
+    }
 }