8
8
// option. This file may not be copied, modified, or distributed
9
9
// except according to those terms.
10
10
11
+ use task:: local_data:: { local_data_pop, local_data_set} ;
12
+
11
13
// helper for transmutation, shown below.
12
- type RustClosure = ( int , int ) ;
14
+ type RustClosure = ( int , int ) ;
15
+
13
16
pub struct Handler < T , U > {
14
17
handle : RustClosure ,
15
18
prev : Option < @Handler < T , U > > ,
16
19
}
17
20
18
21
pub struct Condition < T , U > {
19
22
name : & static /str ,
20
- key : task:: local_data:: LocalDataKey < Handler < T , U > >
23
+ key : task:: local_data:: LocalDataKey < Handler < T , U > >
21
24
}
22
25
23
- impl < T , U > Condition < T , U > {
24
-
25
- fn trap ( & self , h : & self /fn ( & T ) ->U ) -> Trap /& self <T , U > {
26
+ impl < T , U > Condition < T , U > {
27
+ fn trap ( & self , h : & self /fn ( T ) -> U ) -> Trap /& self <T , U > {
26
28
unsafe {
27
29
let p : * RustClosure = :: cast:: transmute ( & h) ;
28
30
let prev = task:: local_data:: local_data_get ( self . key ) ;
29
- let h = @Handler { handle : * p, prev : prev} ;
30
- move Trap { cond : self , handler : h }
31
+ let h = @Handler { handle : * p, prev : prev } ;
32
+ Trap { cond : self , handler : h }
31
33
}
32
34
}
33
35
34
- fn raise ( t : & T ) -> U {
35
- do self . raise_default ( t) {
36
- fail fmt ! ( "Unhandled condition: %s: %?" ,
37
- self . name,
38
- t) ;
39
- }
36
+ fn raise ( t : T ) -> U {
37
+ let msg = fmt ! ( "Unhandled condition: %s: %?" , self . name, t) ;
38
+ self . raise_default ( t, || fail msg)
40
39
}
41
40
42
- fn raise_default ( t : & T , default : fn ( ) -> U ) -> U {
41
+ fn raise_default ( t : T , default : & fn ( ) -> U ) -> U {
43
42
unsafe {
44
- match task :: local_data :: local_data_pop ( self . key ) {
43
+ match local_data_pop ( self . key ) {
45
44
None => {
46
45
debug ! ( "Condition.raise: found no handler" ) ;
47
46
default ( )
48
47
}
49
-
50
48
Some ( handler) => {
51
49
debug ! ( "Condition.raise: found handler" ) ;
52
50
match handler. prev {
53
- None => ( ) ,
54
- Some ( hp) =>
55
- task:: local_data:: local_data_set ( self . key , hp)
51
+ None => { }
52
+ Some ( hp) => local_data_set ( self . key , hp)
56
53
}
57
- let handle : & fn ( & T ) -> U =
54
+ let handle : & fn ( T ) -> U =
58
55
:: cast:: transmute ( handler. handle ) ;
59
56
let u = handle ( t) ;
60
- task:: local_data:: local_data_set ( self . key ,
61
- handler) ;
62
- move u
57
+ local_data_set ( self . key , handler) ;
58
+ u
63
59
}
64
60
}
65
61
}
66
62
}
67
63
}
68
64
69
-
70
-
71
65
struct Trap < T , U > {
72
- cond : & Condition < T , U > ,
66
+ cond : & Condition < T , U > ,
73
67
handler : @Handler < T , U >
74
68
}
75
69
76
- impl < T , U > Trap < T , U > {
70
+ impl < T , U > Trap < T , U > {
77
71
fn in < V > ( & self , inner : & self /fn ( ) -> V ) -> V {
78
72
unsafe {
79
73
let _g = Guard { cond : self . cond } ;
80
74
debug ! ( "Trap: pushing handler to TLS" ) ;
81
- task :: local_data :: local_data_set ( self . cond . key , self . handler ) ;
75
+ local_data_set ( self . cond . key , self . handler ) ;
82
76
inner ( )
83
77
}
84
78
}
85
79
}
86
80
87
81
struct Guard < T , U > {
88
- cond : & Condition < T , U > ,
89
- drop {
82
+ cond : & Condition < T , U >
83
+ }
84
+
85
+ impl < T , U > Guard < T , U > : Drop {
86
+ fn finalize ( & self ) {
90
87
unsafe {
91
88
debug ! ( "Guard: popping handler from TLS" ) ;
92
- let curr = task :: local_data :: local_data_pop ( self . cond. key) ;
89
+ let curr = local_data_pop ( self . cond . key ) ;
93
90
match curr {
94
- None => ( ) ,
95
- Some ( h) =>
96
- match h. prev {
97
- None => ( ) ,
98
- Some ( hp) => {
99
- task:: local_data:: local_data_set ( self . cond . key , hp)
100
- }
91
+ None => { }
92
+ Some ( h) => match h. prev {
93
+ None => { }
94
+ Some ( hp) => local_data_set ( self . cond . key , hp)
101
95
}
102
96
}
103
97
}
104
98
}
105
99
}
106
100
107
-
108
101
#[ cfg( test) ]
109
102
mod test {
110
-
111
103
condition ! {
112
104
sadness: int -> int;
113
105
}
114
106
115
107
fn trouble ( i : int ) {
116
- debug ! ( "trouble: raising conition " ) ;
117
- let j = sadness:: cond. raise ( & i) ;
108
+ debug ! ( "trouble: raising condition " ) ;
109
+ let j = sadness:: cond. raise ( i) ;
118
110
debug ! ( "trouble: handler recovered with %d" , j) ;
119
111
}
120
112
121
113
fn nested_trap_test_inner ( ) {
122
-
123
114
let mut inner_trapped = false ;
124
115
125
116
do sadness:: cond. trap ( |_j| {
@@ -136,7 +127,6 @@ mod test {
136
127
137
128
#[ test]
138
129
fn nested_trap_test_outer ( ) {
139
-
140
130
let mut outer_trapped = false ;
141
131
142
132
do sadness:: cond. trap ( |_j| {
@@ -152,15 +142,14 @@ mod test {
152
142
}
153
143
154
144
fn nested_reraise_trap_test_inner ( ) {
155
-
156
145
let mut inner_trapped = false ;
157
146
158
147
do sadness:: cond. trap ( |_j| {
159
148
debug ! ( "nested_reraise_trap_test_inner: in handler" ) ;
160
149
inner_trapped = true ;
161
150
let i = 10 ;
162
151
debug ! ( "nested_reraise_trap_test_inner: handler re-raising" ) ;
163
- sadness:: cond. raise ( & i)
152
+ sadness:: cond. raise ( i)
164
153
} ) . in {
165
154
debug ! ( "nested_reraise_trap_test_inner: in protected block" ) ;
166
155
trouble ( 1 ) ;
@@ -171,7 +160,6 @@ mod test {
171
160
172
161
#[ test]
173
162
fn nested_reraise_trap_test_outer ( ) {
174
-
175
163
let mut outer_trapped = false ;
176
164
177
165
do sadness:: cond. trap ( |_j| {
@@ -187,18 +175,16 @@ mod test {
187
175
188
176
#[ test]
189
177
fn test_default ( ) {
190
-
191
178
let mut trapped = false ;
192
179
193
180
do sadness:: cond. trap ( |j| {
194
181
debug ! ( "test_default: in handler" ) ;
195
- sadness:: cond. raise_default ( j, || { trapped=true ; 5 } )
182
+ sadness:: cond. raise_default ( j, || { trapped=true ; 5 } )
196
183
} ) . in {
197
184
debug ! ( "test_default: in protected block" ) ;
198
185
trouble ( 1 ) ;
199
186
}
200
187
201
188
assert trapped;
202
189
}
203
-
204
190
}
0 commit comments