@@ -50,9 +50,9 @@ use std::borrow;
50
50
51
51
/// As sync::condvar, a mechanism for unlock-and-descheduling and signaling.
52
52
pub struct Condvar < ' self > {
53
- is_mutex : bool ,
54
- failed : & ' self mut bool ,
55
- cond : & ' self sync:: Condvar < ' self >
53
+ priv is_mutex : bool ,
54
+ priv failed : & ' self mut bool ,
55
+ priv cond : & ' self sync:: Condvar < ' self >
56
56
}
57
57
58
58
impl < ' self > Condvar < ' self > {
@@ -108,7 +108,7 @@ impl<'self> Condvar<'self> {
108
108
****************************************************************************/
109
109
110
110
/// An atomically reference counted wrapper for shared immutable state.
111
- pub struct ARC < T > { x : UnsafeAtomicRcBox < T > }
111
+ pub struct ARC < T > { priv x: UnsafeAtomicRcBox < T > }
112
112
113
113
/// Create an atomically reference counted wrapper.
114
114
pub fn ARC < T : Freeze + Send > ( data : T ) -> ARC < T > {
@@ -123,6 +123,20 @@ impl<T:Freeze+Send> ARC<T> {
123
123
pub fn get < ' a > ( & ' a self ) -> & ' a T {
124
124
unsafe { & * self . x . get_immut ( ) }
125
125
}
126
+
127
+ /**
128
+ * Retrieve the data back out of the ARC. This function blocks until the
129
+ * reference given to it is the last existing one, and then unwrap the data
130
+ * instead of destroying it.
131
+ *
132
+ * If multiple tasks call unwrap, all but the first will fail. Do not call
133
+ * unwrap from a task that holds another reference to the same ARC; it is
134
+ * guaranteed to deadlock.
135
+ */
136
+ pub fn unwrap ( self ) -> T {
137
+ let ARC { x : x } = self ;
138
+ unsafe { x. unwrap ( ) }
139
+ }
126
140
}
127
141
128
142
/**
@@ -143,9 +157,9 @@ impl<T:Freeze + Send> Clone for ARC<T> {
143
157
****************************************************************************/
144
158
145
159
#[ doc( hidden) ]
146
- struct MutexARCInner < T > { lock : Mutex , failed : bool , data : T }
160
+ struct MutexARCInner < T > { priv lock : Mutex , priv failed : bool , priv data : T }
147
161
/// An ARC with mutable data protected by a blocking mutex.
148
- struct MutexARC < T > { x : UnsafeAtomicRcBox < MutexARCInner < T > > }
162
+ struct MutexARC < T > { priv x: UnsafeAtomicRcBox < MutexARCInner < T > > }
149
163
150
164
/// Create a mutex-protected ARC with the supplied data.
151
165
pub fn MutexARC < T : Send > ( user_data : T ) -> MutexARC < T > {
@@ -225,6 +239,22 @@ impl<T:Send> MutexARC<T> {
225
239
cond : cond } )
226
240
}
227
241
}
242
+
243
+ /**
244
+ * Retrieves the data, blocking until all other references are dropped,
245
+ * exactly as arc::unwrap.
246
+ *
247
+ * Will additionally fail if another task has failed while accessing the arc.
248
+ */
249
+ pub fn unwrap ( self ) -> T {
250
+ let MutexARC { x : x } = self ;
251
+ let inner = unsafe { x. unwrap ( ) } ;
252
+ let MutexARCInner { failed : failed, data : data, _ } = inner;
253
+ if failed {
254
+ fail ! ( ~"Can ' t unwrap poisoned MutexARC - another task failed inside!");
255
+ }
256
+ data
257
+ }
228
258
}
229
259
230
260
// Common code for {mutex.access,rwlock.write}{,_cond}.
@@ -268,7 +298,7 @@ fn PoisonOnFail<'r>(failed: &'r mut bool) -> PoisonOnFail {
268
298
****************************************************************************/
269
299
270
300
#[doc(hidden)]
271
- struct RWARCInner < T > { lock : RWlock , failed : bool , data : T }
301
+ struct RWARCInner<T> { priv lock: RWlock, priv failed: bool, priv data: T }
272
302
/**
273
303
* A dual-mode ARC protected by a reader-writer lock. The data can be accessed
274
304
* mutably or immutably, and immutably-accessing tasks may run concurrently.
@@ -278,7 +308,7 @@ struct RWARCInner<T> { lock: RWlock, failed: bool, data: T }
278
308
#[mutable] // XXX remove after snap
279
309
#[no_freeze]
280
310
struct RWARC<T> {
281
- x : UnsafeAtomicRcBox < RWARCInner < T > > ,
311
+ priv x: UnsafeAtomicRcBox<RWARCInner<T>>,
282
312
}
283
313
284
314
/// Create a reader/writer ARC with the supplied data.
@@ -429,6 +459,23 @@ impl<T:Freeze + Send> RWARC<T> {
429
459
}
430
460
}
431
461
}
462
+
463
+ /**
464
+ * Retrieves the data, blocking until all other references are dropped,
465
+ * exactly as arc::unwrap.
466
+ *
467
+ * Will additionally fail if another task has failed while accessing the arc
468
+ * in write mode.
469
+ */
470
+ pub fn unwrap(self) -> T {
471
+ let RWARC { x: x, _ } = self;
472
+ let inner = unsafe { x.unwrap() };
473
+ let RWARCInner { failed: failed, data: data, _ } = inner;
474
+ if failed {
475
+ fail!(~" Can ' t unwrap poisoned RWARC - another task failed inside!")
476
+ }
477
+ data
478
+ }
432
479
}
433
480
434
481
// Borrowck rightly complains about immutably aliasing the rwlock in order to
@@ -611,6 +658,23 @@ mod tests {
611
658
}
612
659
}
613
660
#[test] #[should_fail] #[ignore(cfg(windows))]
661
+ pub fn test_mutex_arc_unwrap_poison() {
662
+ let arc = MutexARC(1);
663
+ let arc2 = ~(&arc).clone();
664
+ let (p, c) = comm::stream();
665
+ do task::spawn {
666
+ unsafe {
667
+ do arc2.access |one| {
668
+ c.send(());
669
+ assert!(*one == 2);
670
+ }
671
+ }
672
+ }
673
+ let _ = p.recv();
674
+ let one = arc.unwrap();
675
+ assert!(one == 1);
676
+ }
677
+ #[test] #[should_fail] #[ignore(cfg(windows))]
614
678
fn test_rw_arc_poison_wr() {
615
679
let arc = ~RWARC(1);
616
680
let arc2 = (*arc).clone();
0 commit comments