@@ -51,6 +51,11 @@ struct HandleBlock<T, U:Copy> {
51
51
}
52
52
}
53
53
54
+ struct Trap < T , U : Copy > {
55
+ cond : & Condition < T , U > ,
56
+ handler : @Handler < T , U >
57
+ }
58
+
54
59
impl < T , U : Copy > ProtectBlock < T , U > {
55
60
fn handle ( & self , h : & self /fn ( & T ) ->U ) -> HandleBlock /& self <T , U > {
56
61
unsafe {
@@ -65,6 +70,20 @@ impl<T, U: Copy> ProtectBlock<T,U> {
65
70
}
66
71
67
72
73
+
74
+ impl < T , U : Copy > Trap < T , U > {
75
+ fn in < V : Copy > ( & self , inner : & self /fn ( ) -> V ) -> V {
76
+ unsafe {
77
+ let prev = task:: local_data:: local_data_get ( self . cond . key ) ;
78
+ let _g = Guard { cond : self . cond ,
79
+ prev : prev } ;
80
+ debug ! ( "Trap: pushing handler to TLS" ) ;
81
+ task:: local_data:: local_data_set ( self . cond . key , self . handler ) ;
82
+ inner ( )
83
+ }
84
+ }
85
+ }
86
+
68
87
impl < T , U : Copy > Condition < T , U > {
69
88
70
89
fn guard ( & self , h : & self /fn ( & T ) ->U ) -> Guard /& self <T , U > {
@@ -79,6 +98,14 @@ impl<T, U: Copy> Condition<T,U> {
79
98
}
80
99
}
81
100
101
+ fn trap ( & self , h : & self /fn ( & T ) ->U ) -> Trap /& self <T , U > {
102
+ unsafe {
103
+ let p : * RustClosure = :: cast:: transmute ( & h) ;
104
+ let h = @Handler { handle : * p} ;
105
+ move Trap { cond : self , handler : h }
106
+ }
107
+ }
108
+
82
109
fn protect ( & self , inner : & self /fn ( ) ) -> ProtectBlock /& self <T , U > {
83
110
unsafe {
84
111
// transmutation to avoid copying non-copyable, should
@@ -229,3 +256,45 @@ fn nested_guard_test_outer() {
229
256
230
257
assert outer_trapped;
231
258
}
259
+
260
+
261
+
262
+ #[ cfg( test) ]
263
+ fn nested_trap_test_inner ( ) {
264
+ let sadness_condition : Condition < int , int > =
265
+ Condition { key : sadness_key } ;
266
+
267
+ let mut inner_trapped = false ;
268
+
269
+ do sadness_condition. trap ( |_j| {
270
+ debug ! ( "nested_trap_test_inner: in handler" ) ;
271
+ inner_trapped = true ;
272
+ 0
273
+ } ) . in {
274
+ debug ! ( "nested_trap_test_inner: in protected block" ) ;
275
+ trouble ( 1 ) ;
276
+ }
277
+
278
+ assert inner_trapped;
279
+ }
280
+
281
+ #[ test]
282
+ fn nested_trap_test_outer ( ) {
283
+
284
+ let sadness_condition : Condition < int , int > =
285
+ Condition { key : sadness_key } ;
286
+
287
+ let mut outer_trapped = false ;
288
+
289
+ do sadness_condition. trap ( |_j| {
290
+ debug ! ( "nested_trap_test_outer: in handler" ) ;
291
+ outer_trapped = true ; 0
292
+ } ) . in {
293
+ debug ! ( "nested_guard_test_outer: in protected block" ) ;
294
+ nested_trap_test_inner ( ) ;
295
+ trouble ( 1 ) ;
296
+ }
297
+
298
+
299
+ assert outer_trapped;
300
+ }
0 commit comments