Skip to content

Commit 463efaf

Browse files
committed
---
yaml --- r: 34793 b: refs/heads/master c: fdd7b4d h: refs/heads/master i: 34791: cb155b4 v: v3
1 parent d968d78 commit 463efaf

File tree

3 files changed

+119
-1
lines changed

3 files changed

+119
-1
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
refs/heads/master: e7e1bab27fa8341467b5160506bbd580b5f6bbb7
2+
refs/heads/master: fdd7b4d8f4df135f30a3f04ff2f777bce1277d2a
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
44
refs/heads/snap-stage3: eb8fd119c65c67f3b1b8268cc7341c22d39b7b61
55
refs/heads/try: d324a424d8f84b1eb049b12cf34182bda91b0024

trunk/src/libcore/condition.rs

Lines changed: 117 additions & 0 deletions
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+
}

trunk/src/libcore/core.rc

Lines changed: 1 addition & 0 deletions
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)