Skip to content

Commit

Permalink
clean up condition module:
Browse files Browse the repository at this point in the history
* use Drop trait in Guard
* fix formatting
* remove bare function in Condition.raise_default
* use moved types instead of borrowed pointers in Condition.{raise,trap}
* import common functions
  • Loading branch information
apasel422 committed Dec 25, 2012
1 parent 56227c4 commit ec444c0
Showing 1 changed file with 36 additions and 50 deletions.
86 changes: 36 additions & 50 deletions src/libcore/condition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,118 +8,109 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use task::local_data::{local_data_pop, local_data_set};

// helper for transmutation, shown below.
type RustClosure = (int,int);
type RustClosure = (int, int);

pub struct Handler<T, U> {
handle: RustClosure,
prev: Option<@Handler<T, U>>,
}

pub struct Condition<T, U> {
name: &static/str,
key: task::local_data::LocalDataKey<Handler<T,U>>
key: task::local_data::LocalDataKey<Handler<T, U>>
}

impl<T, U> Condition<T,U> {

fn trap(&self, h: &self/fn(&T) ->U) -> Trap/&self<T,U> {
impl<T, U> Condition<T, U> {
fn trap(&self, h: &self/fn(T) -> U) -> Trap/&self<T, U> {
unsafe {
let p : *RustClosure = ::cast::transmute(&h);
let prev = task::local_data::local_data_get(self.key);
let h = @Handler{handle: *p, prev: prev};
move Trap { cond: self, handler: h }
let h = @Handler { handle: *p, prev: prev };
Trap { cond: self, handler: h }
}
}

fn raise(t:&T) -> U {
do self.raise_default(t) {
fail fmt!("Unhandled condition: %s: %?",
self.name,
t);
}
fn raise(t: T) -> U {
let msg = fmt!("Unhandled condition: %s: %?", self.name, t);
self.raise_default(t, || fail msg)
}

fn raise_default(t:&T, default: fn() -> U) -> U {
fn raise_default(t: T, default: &fn() -> U) -> U {
unsafe {
match task::local_data::local_data_pop(self.key) {
match local_data_pop(self.key) {
None => {
debug!("Condition.raise: found no handler");
default()
}

Some(handler) => {
debug!("Condition.raise: found handler");
match handler.prev {
None => (),
Some(hp) =>
task::local_data::local_data_set(self.key, hp)
None => {}
Some(hp) => local_data_set(self.key, hp)
}
let handle : &fn(&T) -> U =
let handle : &fn(T) -> U =
::cast::transmute(handler.handle);
let u = handle(t);
task::local_data::local_data_set(self.key,
handler);
move u
local_data_set(self.key, handler);
u
}
}
}
}
}



struct Trap<T, U> {
cond: &Condition<T,U>,
cond: &Condition<T, U>,
handler: @Handler<T, U>
}

impl<T, U> Trap<T,U> {
impl<T, U> Trap<T, U> {
fn in<V>(&self, inner: &self/fn() -> V) -> V {
unsafe {
let _g = Guard { cond: self.cond };
debug!("Trap: pushing handler to TLS");
task::local_data::local_data_set(self.cond.key, self.handler);
local_data_set(self.cond.key, self.handler);
inner()
}
}
}

struct Guard<T, U> {
cond: &Condition<T,U>,
drop {
cond: &Condition<T, U>
}

impl<T, U> Guard<T, U> : Drop {
fn finalize(&self) {
unsafe {
debug!("Guard: popping handler from TLS");
let curr = task::local_data::local_data_pop(self.cond.key);
let curr = local_data_pop(self.cond.key);
match curr {
None => (),
Some(h) =>
match h.prev {
None => (),
Some(hp) => {
task::local_data::local_data_set(self.cond.key, hp)
}
None => {}
Some(h) => match h.prev {
None => {}
Some(hp) => local_data_set(self.cond.key, hp)
}
}
}
}
}


#[cfg(test)]
mod test {

condition! {
sadness: int -> int;
}

fn trouble(i: int) {
debug!("trouble: raising conition");
let j = sadness::cond.raise(&i);
debug!("trouble: raising condition");
let j = sadness::cond.raise(i);
debug!("trouble: handler recovered with %d", j);
}

fn nested_trap_test_inner() {

let mut inner_trapped = false;

do sadness::cond.trap(|_j| {
Expand All @@ -136,7 +127,6 @@ mod test {

#[test]
fn nested_trap_test_outer() {

let mut outer_trapped = false;

do sadness::cond.trap(|_j| {
Expand All @@ -152,15 +142,14 @@ mod test {
}

fn nested_reraise_trap_test_inner() {

let mut inner_trapped = false;

do sadness::cond.trap(|_j| {
debug!("nested_reraise_trap_test_inner: in handler");
inner_trapped = true;
let i = 10;
debug!("nested_reraise_trap_test_inner: handler re-raising");
sadness::cond.raise(&i)
sadness::cond.raise(i)
}).in {
debug!("nested_reraise_trap_test_inner: in protected block");
trouble(1);
Expand All @@ -171,7 +160,6 @@ mod test {

#[test]
fn nested_reraise_trap_test_outer() {

let mut outer_trapped = false;

do sadness::cond.trap(|_j| {
Expand All @@ -187,18 +175,16 @@ mod test {

#[test]
fn test_default() {

let mut trapped = false;

do sadness::cond.trap(|j| {
debug!("test_default: in handler");
sadness::cond.raise_default(j, || {trapped=true; 5})
sadness::cond.raise_default(j, || { trapped=true; 5 })
}).in {
debug!("test_default: in protected block");
trouble(1);
}

assert trapped;
}

}

1 comment on commit ec444c0

@graydon
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

r+, thanks

Please sign in to comment.