Skip to content

Commit fdd7b4d

Browse files
committed
core: first working sketch of a condition system.
1 parent e7e1bab commit fdd7b4d

File tree

2 files changed

+118
-0
lines changed

2 files changed

+118
-0
lines changed

src/libcore/condition.rs

+117
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
// helper for transmutation, shown below.
2+
type RustClosure = (int,int);
3+
4+
struct Condition {
5+
key: task::local_data::LocalDataKey<Handler>
6+
}
7+
8+
struct Handler {
9+
// Handler should link to previous handler and
10+
// reinstall it when popped.
11+
handle: RustClosure
12+
}
13+
14+
15+
struct ProtectBlock {
16+
cond: &Condition,
17+
inner: RustClosure
18+
}
19+
20+
struct PopHandler {
21+
cond: &Condition,
22+
drop {
23+
unsafe {
24+
task::local_data::local_data_pop(self.cond.key);
25+
}
26+
}
27+
}
28+
29+
struct HandleBlock {
30+
pb: &ProtectBlock,
31+
handler: @Handler,
32+
drop {
33+
unsafe {
34+
task::local_data::local_data_set(self.pb.cond.key,
35+
self.handler);
36+
let _pop = PopHandler { cond: self.pb.cond };
37+
// transmutation to avoid copying non-copyable, should
38+
// be fixable by tracking closure pointees in regionck.
39+
let f : &fn() = ::cast::transmute(self.pb.inner);
40+
f();
41+
}
42+
}
43+
}
44+
45+
impl ProtectBlock {
46+
fn handle<T, U: Copy>(&self, h: &self/fn(&T) ->U) -> HandleBlock/&self {
47+
unsafe {
48+
let p : *RustClosure = ::cast::transmute(&h);
49+
HandleBlock { pb: self,
50+
handler: @Handler{handle: *p} }
51+
}
52+
}
53+
}
54+
55+
56+
impl Condition {
57+
58+
fn protect(&self, inner: &self/fn()) -> ProtectBlock/&self {
59+
unsafe {
60+
// transmutation to avoid copying non-copyable, should
61+
// be fixable by tracking closure pointees in regionck.
62+
let p : *RustClosure = ::cast::transmute(&inner);
63+
ProtectBlock { cond: self,
64+
inner: *p } }
65+
}
66+
67+
fn raise<T, U: Copy>(t:&T) -> U {
68+
unsafe {
69+
match task::local_data::local_data_get(self.key) {
70+
None => fail,
71+
Some(handler) => {
72+
io::println("got handler");
73+
let f : &fn(&T) -> U = ::cast::transmute(handler.handle);
74+
f(t)
75+
}
76+
}
77+
}
78+
}
79+
}
80+
81+
82+
#[test]
83+
fn happiness_key(_x: @Handler) { }
84+
85+
#[test]
86+
fn sadness_key(_x: @Handler) { }
87+
88+
#[test]
89+
fn trouble(i: int) {
90+
// Condition should work as a const, just limitations in consts.
91+
let sadness_condition : Condition = Condition { key: sadness_key };
92+
io::println("raising");
93+
let j = sadness_condition.raise(&i);
94+
io::println(fmt!("handler recovered with %d", j));
95+
}
96+
97+
#[test]
98+
fn test() {
99+
100+
let sadness_condition : Condition = Condition { key: sadness_key };
101+
102+
let mut i = 10;
103+
104+
let b = do sadness_condition.protect {
105+
io::println("in protected block");
106+
trouble(1);
107+
trouble(2);
108+
trouble(3);
109+
};
110+
111+
do b.handle |j| {
112+
i += *j;
113+
i
114+
};
115+
116+
assert i == 16;
117+
}

src/libcore/core.rc

+1
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ pub mod flate;
200200
pub mod repr;
201201
pub mod cleanup;
202202
pub mod reflect;
203+
pub mod condition;
203204

204205
// Modules supporting compiler-generated code
205206
// Exported but not part of the public interface

0 commit comments

Comments
 (0)