about summary refs log tree commit diff
path: root/src/libcore
diff options
context:
space:
mode:
authorGraydon Hoare <graydon@mozilla.com>2012-10-18 19:47:19 -0700
committerGraydon Hoare <graydon@mozilla.com>2012-10-18 20:08:14 -0700
commitc97944fbf810720c2bcb0ccbe1c3149a3d9be4c0 (patch)
treee063914fa1cb3bc4c47ac9da555095a7c536a78c /src/libcore
parent6c4ad31f764aa8ebec3873ce68770b4173b0b97d (diff)
core: add potential "simpler interface" to core::condition, also reduce TLS hits.
Diffstat (limited to 'src/libcore')
-rw-r--r--src/libcore/condition.rs87
1 files changed, 69 insertions, 18 deletions
diff --git a/src/libcore/condition.rs b/src/libcore/condition.rs
index d50c01683d8..a50c29b0f92 100644
--- a/src/libcore/condition.rs
+++ b/src/libcore/condition.rs
@@ -6,8 +6,7 @@ struct Condition<T, U:Copy> {
 }
 
 struct Handler<T, U:Copy> {
-    handle: RustClosure,
-    prev: Option<@Handler<T, U>>
+    handle: RustClosure
 }
 
 
@@ -16,20 +15,16 @@ struct ProtectBlock<T, U:Copy> {
     inner: RustClosure
 }
 
-struct PopHandler<T, U:Copy> {
+struct Guard<T, U:Copy> {
     cond: &Condition<T,U>,
+    prev: Option<@Handler<T, U>>,
     drop {
-        unsafe {
-            debug!("PopHandler: popping handler from TLS");
-            match task::local_data::local_data_pop(self.cond.key) {
-                None => (),
-                Some(h) => {
-                    match h.prev {
-                        None => (),
-                        Some(p) =>
-                        task::local_data::local_data_set(self.cond.key, p)
-                    }
-                }
+        match self.prev {
+            None => (),
+            Some(p) =>
+            unsafe {
+                debug!("Guard: popping handler from TLS");
+                task::local_data::local_data_set(self.cond.key, p)
             }
         }
     }
@@ -37,13 +32,15 @@ struct PopHandler<T, U:Copy> {
 
 struct HandleBlock<T, U:Copy> {
     pb: &ProtectBlock<T,U>,
+    prev: Option<@Handler<T,U>>,
     handler: @Handler<T,U>,
     drop {
         unsafe {
             debug!("HandleBlock: pushing handler to TLS");
+            let _g = Guard { cond: self.pb.cond,
+                             prev: self.prev };
             task::local_data::local_data_set(self.pb.cond.key,
                                              self.handler);
-            let _pop = PopHandler { cond: self.pb.cond };
             // transmutation to avoid copying non-copyable, should
             // be fixable by tracking closure pointees in regionck.
             let f : &fn() = ::cast::transmute(self.pb.inner);
@@ -61,7 +58,8 @@ impl<T, U: Copy> ProtectBlock<T,U> {
             let p : *RustClosure = ::cast::transmute(&h);
             let prev = task::local_data::local_data_get(self.cond.key);
             HandleBlock { pb: self,
-                          handler: @Handler{handle: *p, prev: prev} }
+                          prev: prev,
+                          handler: @Handler{handle: *p} }
         }
     }
 }
@@ -69,6 +67,18 @@ impl<T, U: Copy> ProtectBlock<T,U> {
 
 impl<T, U: Copy>  Condition<T,U> {
 
+    fn guard(&self, h: &self/fn(&T) ->U) -> Guard/&self<T,U> {
+        unsafe {
+            let prev = task::local_data::local_data_get(self.key);
+            let g = Guard { cond: self, prev: prev };
+            debug!("Guard: pushing handler to TLS");
+            let p : *RustClosure = ::cast::transmute(&h);
+            let h = @Handler{handle: *p};
+            task::local_data::local_data_set(self.key, h);
+            move g
+        }
+    }
+
     fn protect(&self, inner: &self/fn()) -> ProtectBlock/&self<T,U> {
         unsafe {
             // transmutation to avoid copying non-copyable, should
@@ -147,7 +157,7 @@ fn nested_test_inner() {
         trouble(1);
     };
 
-    do b.handle |_j:&int| {
+    do b.handle |_j| {
         debug!("nested_test_inner: in handler");
         inner_trapped = true;
         0
@@ -170,7 +180,7 @@ fn nested_test_outer() {
         trouble(1);
     };
 
-    do b.handle |_j:&int| {
+    do b.handle |_j| {
         debug!("nested_test_outer: in handler");
         outer_trapped = true;
         0
@@ -178,3 +188,44 @@ fn nested_test_outer() {
 
     assert outer_trapped;
 }
+
+
+#[cfg(test)]
+fn nested_guard_test_inner() {
+    let sadness_condition : Condition<int,int> =
+        Condition { key: sadness_key };
+
+    let mut inner_trapped = false;
+
+    let _g = do sadness_condition.guard |_j| {
+        debug!("nested_guard_test_inner: in handler");
+        inner_trapped = true;
+        0
+    };
+
+    debug!("nested_guard_test_inner: in protected block");
+    trouble(1);
+
+    assert inner_trapped;
+}
+
+#[test]
+fn nested_guard_test_outer() {
+
+    let sadness_condition : Condition<int,int> =
+        Condition { key: sadness_key };
+
+    let mut outer_trapped = false;
+
+    let _g = do sadness_condition.guard |_j| {
+        debug!("nested_guard_test_outer: in handler");
+        outer_trapped = true;
+        0
+    };
+
+    debug!("nested_guard_test_outer: in protected block");
+    nested_guard_test_inner();
+    trouble(1);
+
+    assert outer_trapped;
+}