about summary refs log tree commit diff
path: root/src/libcore
diff options
context:
space:
mode:
authorGraydon Hoare <graydon@mozilla.com>2012-10-19 14:46:32 -0700
committerGraydon Hoare <graydon@mozilla.com>2012-10-19 14:46:49 -0700
commit89de49cecdf5e48497e5770eba13240091627320 (patch)
treee8f5fbce12b7a61b4c22d249db7eef440657217b /src/libcore
parent0243d86e19295d9e25e6fa83005f0aa03eef519e (diff)
core: add 3rd proposed interface (trap/in) to conditions.
Diffstat (limited to 'src/libcore')
-rw-r--r--src/libcore/condition.rs69
1 files changed, 69 insertions, 0 deletions
diff --git a/src/libcore/condition.rs b/src/libcore/condition.rs
index a50c29b0f92..77bd88e04d7 100644
--- a/src/libcore/condition.rs
+++ b/src/libcore/condition.rs
@@ -51,6 +51,11 @@ struct HandleBlock<T, U:Copy> {
     }
 }
 
+struct Trap<T, U:Copy> {
+    cond: &Condition<T,U>,
+    handler: @Handler<T, U>
+}
+
 impl<T, U: Copy> ProtectBlock<T,U> {
     fn handle(&self, h: &self/fn(&T) ->U) -> HandleBlock/&self<T,U> {
         unsafe {
@@ -65,6 +70,20 @@ impl<T, U: Copy> ProtectBlock<T,U> {
 }
 
 
+
+impl<T, U: Copy> Trap<T,U> {
+    fn in<V: Copy>(&self, inner: &self/fn() -> V) -> V {
+        unsafe {
+            let prev = task::local_data::local_data_get(self.cond.key);
+            let _g = Guard { cond: self.cond,
+                             prev: prev };
+            debug!("Trap: pushing handler to TLS");
+            task::local_data::local_data_set(self.cond.key, self.handler);
+            inner()
+        }
+    }
+}
+
 impl<T, U: Copy>  Condition<T,U> {
 
     fn guard(&self, h: &self/fn(&T) ->U) -> Guard/&self<T,U> {
@@ -79,6 +98,14 @@ impl<T, U: Copy>  Condition<T,U> {
         }
     }
 
+    fn trap(&self, h: &self/fn(&T) ->U) -> Trap/&self<T,U> {
+        unsafe {
+            let p : *RustClosure = ::cast::transmute(&h);
+            let h = @Handler{handle: *p};
+            move Trap { cond: self, handler: h }
+        }
+    }
+
     fn protect(&self, inner: &self/fn()) -> ProtectBlock/&self<T,U> {
         unsafe {
             // transmutation to avoid copying non-copyable, should
@@ -229,3 +256,45 @@ fn nested_guard_test_outer() {
 
     assert outer_trapped;
 }
+
+
+
+#[cfg(test)]
+fn nested_trap_test_inner() {
+    let sadness_condition : Condition<int,int> =
+        Condition { key: sadness_key };
+
+    let mut inner_trapped = false;
+
+    do sadness_condition.trap(|_j| {
+        debug!("nested_trap_test_inner: in handler");
+        inner_trapped = true;
+        0
+    }).in {
+        debug!("nested_trap_test_inner: in protected block");
+        trouble(1);
+    }
+
+    assert inner_trapped;
+}
+
+#[test]
+fn nested_trap_test_outer() {
+
+    let sadness_condition : Condition<int,int> =
+        Condition { key: sadness_key };
+
+    let mut outer_trapped = false;
+
+    do sadness_condition.trap(|_j| {
+        debug!("nested_trap_test_outer: in handler");
+        outer_trapped = true; 0
+    }).in {
+        debug!("nested_guard_test_outer: in protected block");
+        nested_trap_test_inner();
+        trouble(1);
+    }
+
+
+    assert outer_trapped;
+}