Skip to content

Commit 80d9199

Browse files
committed
---
yaml --- r: 142999 b: refs/heads/try2 c: 10a400f h: refs/heads/master i: 142997: 164b0f6 142995: 2554009 142991: a2dfae6 v: v3
1 parent 498af63 commit 80d9199

File tree

3 files changed

+284
-28
lines changed

3 files changed

+284
-28
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ refs/heads/snap-stage3: 78a7676898d9f80ab540c6df5d4c9ce35bb50463
55
refs/heads/try: 519addf6277dbafccbb4159db4b710c37eaa2ec5
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b
8-
refs/heads/try2: 55adc4467b4364d949774d5bfd1eba4a16c0b810
8+
refs/heads/try2: 10a400ffaa8b67add66a62bde0ef3c415d7aed5f
99
refs/heads/dist-snap: ba4081a5a8573875fed17545846f6f6902c8ba8d
1010
refs/tags/release-0.2: c870d2dffb391e14efb05aa27898f1f6333a9596
1111
refs/tags/release-0.3: b5f0d0f648d9a6153664837026ba1be43d3e2503

branches/try2/src/libextra/arc.rs

Lines changed: 72 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,9 @@ use std::borrow;
5050

5151
/// As sync::condvar, a mechanism for unlock-and-descheduling and signaling.
5252
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>
5656
}
5757

5858
impl<'self> Condvar<'self> {
@@ -108,7 +108,7 @@ impl<'self> Condvar<'self> {
108108
****************************************************************************/
109109

110110
/// 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> }
112112

113113
/// Create an atomically reference counted wrapper.
114114
pub fn ARC<T:Freeze + Send>(data: T) -> ARC<T> {
@@ -123,6 +123,20 @@ impl<T:Freeze+Send> ARC<T> {
123123
pub fn get<'a>(&'a self) -> &'a T {
124124
unsafe { &*self.x.get_immut() }
125125
}
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+
}
126140
}
127141

128142
/**
@@ -143,9 +157,9 @@ impl<T:Freeze + Send> Clone for ARC<T> {
143157
****************************************************************************/
144158

145159
#[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 }
147161
/// 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>> }
149163

150164
/// Create a mutex-protected ARC with the supplied data.
151165
pub fn MutexARC<T:Send>(user_data: T) -> MutexARC<T> {
@@ -225,6 +239,22 @@ impl<T:Send> MutexARC<T> {
225239
cond: cond })
226240
}
227241
}
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+
}
228258
}
229259
230260
// Common code for {mutex.access,rwlock.write}{,_cond}.
@@ -268,7 +298,7 @@ fn PoisonOnFail<'r>(failed: &'r mut bool) -> PoisonOnFail {
268298
****************************************************************************/
269299
270300
#[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 }
272302
/**
273303
* A dual-mode ARC protected by a reader-writer lock. The data can be accessed
274304
* mutably or immutably, and immutably-accessing tasks may run concurrently.
@@ -278,7 +308,7 @@ struct RWARCInner<T> { lock: RWlock, failed: bool, data: T }
278308
#[mutable] // XXX remove after snap
279309
#[no_freeze]
280310
struct RWARC<T> {
281-
x: UnsafeAtomicRcBox<RWARCInner<T>>,
311+
priv x: UnsafeAtomicRcBox<RWARCInner<T>>,
282312
}
283313
284314
/// Create a reader/writer ARC with the supplied data.
@@ -429,6 +459,23 @@ impl<T:Freeze + Send> RWARC<T> {
429459
}
430460
}
431461
}
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+
}
432479
}
433480
434481
// Borrowck rightly complains about immutably aliasing the rwlock in order to
@@ -611,6 +658,23 @@ mod tests {
611658
}
612659
}
613660
#[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))]
614678
fn test_rw_arc_poison_wr() {
615679
let arc = ~RWARC(1);
616680
let arc2 = (*arc).clone();

0 commit comments

Comments
 (0)