@@ -6,8 +6,7 @@ struct Condition<T, U:Copy> {
6
6
}
7
7
8
8
struct Handler < T , U : Copy > {
9
- handle : RustClosure ,
10
- prev : Option < @Handler < T , U > >
9
+ handle : RustClosure
11
10
}
12
11
13
12
@@ -16,34 +15,32 @@ struct ProtectBlock<T, U:Copy> {
16
15
inner : RustClosure
17
16
}
18
17
19
- struct PopHandler < T , U : Copy > {
18
+ struct Guard < T , U : Copy > {
20
19
cond : & Condition < T , U > ,
20
+ prev : Option < @Handler < T , U > > ,
21
21
drop {
22
- unsafe {
23
- debug!( "PopHandler : popping handler from TLS ") ;
24
- match task:: local_data:: local_data_pop ( self . cond. key) {
25
- None => ( ) ,
26
- Some ( h) => {
27
- match h. prev {
28
- None => ( ) ,
29
- Some ( p) =>
30
- task:: local_data:: local_data_set ( self . cond . key , p)
31
- }
32
- }
22
+ match self . prev {
23
+ None => ( ) ,
24
+ Some ( p) =>
25
+ unsafe {
26
+ debug!( "Guard : popping handler from TLS ") ;
27
+ task:: local_data:: local_data_set ( self . cond. key, p )
33
28
}
34
29
}
35
30
}
36
31
}
37
32
38
33
struct HandleBlock < T , U : Copy > {
39
34
pb : & ProtectBlock < T , U > ,
35
+ prev : Option < @Handler < T , U > > ,
40
36
handler : @Handler < T , U > ,
41
37
drop {
42
38
unsafe {
43
39
debug!( "HandleBlock : pushing handler to TLS ") ;
40
+ let _g = Guard { cond: self . pb. cond ,
41
+ prev : self . prev } ;
44
42
task:: local_data:: local_data_set ( self . pb . cond . key ,
45
43
self . handler ) ;
46
- let _pop = PopHandler { cond : self . pb . cond } ;
47
44
// transmutation to avoid copying non-copyable, should
48
45
// be fixable by tracking closure pointees in regionck.
49
46
let f : & fn ( ) = :: cast:: transmute ( self . pb . inner ) ;
@@ -61,14 +58,27 @@ impl<T, U: Copy> ProtectBlock<T,U> {
61
58
let p : * RustClosure = :: cast:: transmute ( & h) ;
62
59
let prev = task:: local_data:: local_data_get ( self . cond . key ) ;
63
60
HandleBlock { pb: self ,
64
- handler: @Handler { handle: * p, prev: prev} }
61
+ prev: prev,
62
+ handler: @Handler { handle: * p} }
65
63
}
66
64
}
67
65
}
68
66
69
67
70
68
impl < T , U : Copy > Condition < T , U > {
71
69
70
+ fn guard ( & self , h : & self /fn ( & T ) ->U ) -> Guard /& self <T , U > {
71
+ unsafe {
72
+ let prev = task:: local_data:: local_data_get ( self . key ) ;
73
+ let g = Guard { cond : self , prev : prev } ;
74
+ debug ! ( "Guard: pushing handler to TLS" ) ;
75
+ let p : * RustClosure = :: cast:: transmute ( & h) ;
76
+ let h = @Handler { handle : * p} ;
77
+ task:: local_data:: local_data_set ( self . key , h) ;
78
+ move g
79
+ }
80
+ }
81
+
72
82
fn protect ( & self , inner : & self /fn ( ) ) -> ProtectBlock /& self <T , U > {
73
83
unsafe {
74
84
// transmutation to avoid copying non-copyable, should
@@ -147,7 +157,7 @@ fn nested_test_inner() {
147
157
trouble ( 1 ) ;
148
158
} ;
149
159
150
- do b. handle |_j: & int | {
160
+ do b. handle |_j| {
151
161
debug ! ( "nested_test_inner: in handler" ) ;
152
162
inner_trapped = true ;
153
163
0
@@ -170,11 +180,52 @@ fn nested_test_outer() {
170
180
trouble ( 1 ) ;
171
181
} ;
172
182
173
- do b. handle |_j: & int | {
183
+ do b. handle |_j| {
174
184
debug ! ( "nested_test_outer: in handler" ) ;
175
185
outer_trapped = true ;
176
186
0
177
187
} ;
178
188
179
189
assert outer_trapped;
180
190
}
191
+
192
+
193
+ #[ cfg( test) ]
194
+ fn nested_guard_test_inner ( ) {
195
+ let sadness_condition : Condition < int , int > =
196
+ Condition { key : sadness_key } ;
197
+
198
+ let mut inner_trapped = false ;
199
+
200
+ let _g = do sadness_condition. guard |_j| {
201
+ debug ! ( "nested_guard_test_inner: in handler" ) ;
202
+ inner_trapped = true ;
203
+ 0
204
+ } ;
205
+
206
+ debug ! ( "nested_guard_test_inner: in protected block" ) ;
207
+ trouble ( 1 ) ;
208
+
209
+ assert inner_trapped;
210
+ }
211
+
212
+ #[ test]
213
+ fn nested_guard_test_outer ( ) {
214
+
215
+ let sadness_condition : Condition < int , int > =
216
+ Condition { key : sadness_key } ;
217
+
218
+ let mut outer_trapped = false ;
219
+
220
+ let _g = do sadness_condition. guard |_j| {
221
+ debug ! ( "nested_guard_test_outer: in handler" ) ;
222
+ outer_trapped = true ;
223
+ 0
224
+ } ;
225
+
226
+ debug ! ( "nested_guard_test_outer: in protected block" ) ;
227
+ nested_guard_test_inner ( ) ;
228
+ trouble ( 1 ) ;
229
+
230
+ assert outer_trapped;
231
+ }
0 commit comments