@@ -81,11 +81,12 @@ fn clone<T: const send>(rc: &arc<T>) -> arc<T> {
81
81
}
82
82
83
83
// An arc over mutable data that is protected by a lock.
84
- type ex_data < T : send > = { lock : sys:: little_lock , mut data : T } ;
84
+ type ex_data < T : send > =
85
+ { lock : sys:: little_lock , mut failed : bool , mut data : T } ;
85
86
type exclusive < T : send > = arc_destruct < ex_data < T > > ;
86
87
87
88
fn exclusive < T : send > ( -data : T ) -> exclusive < T > {
88
- let data = ~{ mut count: 1 , data : { lock : sys:: little_lock ( ) ,
89
+ let data = ~{ mut count: 1 , data : { lock : sys:: little_lock ( ) , failed : false ,
89
90
data : data} } ;
90
91
unsafe {
91
92
let ptr = unsafe :: reinterpret_cast ( data) ;
@@ -128,12 +129,18 @@ impl<T: send> exclusive<T> {
128
129
let ptr: ~arc_data < ex_data < T > > =
129
130
unsafe :: reinterpret_cast ( self . data ) ;
130
131
assert ptr. count > 0 ;
131
- let r = {
132
- let rec: & ex_data < T > = & ( * ptr) . data ;
133
- do rec. lock . lock { f ( & mut rec. data ) }
134
- } ;
132
+ let ptr2: & arc_data < ex_data < T > > = unsafe :: reinterpret_cast ( & * ptr) ;
135
133
unsafe :: forget ( ptr) ;
136
- r
134
+ let rec: & ex_data < T > = & ( * ptr2) . data ;
135
+ do rec. lock . lock {
136
+ if rec. failed {
137
+ fail ~"Poisoned arc:: exclusive - another task failed inside!";
138
+ }
139
+ rec. failed = true ;
140
+ let result = f ( & mut rec. data ) ;
141
+ rec. failed = false ;
142
+ result
143
+ }
137
144
}
138
145
}
139
146
@@ -168,12 +175,11 @@ mod tests {
168
175
}
169
176
170
177
#[ test]
171
- #[ ignore] // this can probably infinite loop too.
172
178
fn exclusive_arc ( ) {
173
179
let mut futures = ~[ ] ;
174
180
175
181
let num_tasks = 10 u;
176
- let count = 1000 u ;
182
+ let count = 10 u ;
177
183
178
184
let total = exclusive ( ~mut 0 u) ;
179
185
@@ -194,4 +200,20 @@ mod tests {
194
200
assert * * total == num_tasks * count
195
201
} ;
196
202
}
203
+
204
+ #[ test] #[ should_fail] #[ ignore( cfg( windows) ) ]
205
+ fn exclusive_poison ( ) {
206
+ // Tests that if one task fails inside of an exclusive, subsequent
207
+ // accesses will also fail.
208
+ let x = arc:: exclusive ( 1 ) ;
209
+ let x2 = x. clone ( ) ;
210
+ do task:: try {
211
+ do x2. with |one| {
212
+ assert * one == 2 ;
213
+ }
214
+ } ;
215
+ do x. with |one| {
216
+ assert * one == 1 ;
217
+ }
218
+ }
197
219
}
0 commit comments