diff options
| author | Graydon Hoare <graydon@mozilla.com> | 2012-10-19 14:46:32 -0700 |
|---|---|---|
| committer | Graydon Hoare <graydon@mozilla.com> | 2012-10-19 14:46:49 -0700 |
| commit | 89de49cecdf5e48497e5770eba13240091627320 (patch) | |
| tree | e8f5fbce12b7a61b4c22d249db7eef440657217b /src/libcore | |
| parent | 0243d86e19295d9e25e6fa83005f0aa03eef519e (diff) | |
core: add 3rd proposed interface (trap/in) to conditions.
Diffstat (limited to 'src/libcore')
| -rw-r--r-- | src/libcore/condition.rs | 69 |
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; +} |
