diff options
| author | Graydon Hoare <graydon@mozilla.com> | 2012-10-18 19:47:19 -0700 |
|---|---|---|
| committer | Graydon Hoare <graydon@mozilla.com> | 2012-10-18 20:08:14 -0700 |
| commit | c97944fbf810720c2bcb0ccbe1c3149a3d9be4c0 (patch) | |
| tree | e063914fa1cb3bc4c47ac9da555095a7c536a78c /src/libcore | |
| parent | 6c4ad31f764aa8ebec3873ce68770b4173b0b97d (diff) | |
core: add potential "simpler interface" to core::condition, also reduce TLS hits.
Diffstat (limited to 'src/libcore')
| -rw-r--r-- | src/libcore/condition.rs | 87 |
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; +} |
