Add unwrap for std::arc ARC variants

This commit is contained in:
Ben Blum 2012-08-20 17:58:59 -04:00
parent 05accaa167
commit 1aa50bba7c

View File

@ -6,8 +6,8 @@
* between tasks.
*/
import unsafe::{SharedMutableState,
shared_mutable_state, clone_shared_mutable_state,
import unsafe::{SharedMutableState, shared_mutable_state,
clone_shared_mutable_state, unwrap_shared_mutable_state,
get_shared_mutable_state, get_shared_immutable_state};
import sync;
import sync::{mutex, mutex_with_condvars, rwlock, rwlock_with_condvars};
@ -93,6 +93,12 @@ fn clone<T: const send>(rc: &arc<T>) -> arc<T> {
arc { x: unsafe { clone_shared_mutable_state(&rc.x) } }
}
#[cfg(stage1)]
fn unwrap<T: const send>(+rc: arc<T>) -> T {
let arc { x: x } = rc;
unsafe { unwrap_shared_mutable_state(x) }
}
/****************************************************************************
* Mutex protected ARC (unsafe)
****************************************************************************/
@ -181,6 +187,18 @@ impl<T: send> &mutex_arc<T> {
}
}
// FIXME(#2585) make this a by-move method on the arc
#[cfg(stage1)]
fn unwrap_mutex_arc<T: send>(+arc: mutex_arc<T>) -> T {
let mutex_arc { x: x } = arc;
let inner = unsafe { unwrap_shared_mutable_state(x) };
let mutex_arc_inner { failed: failed, data: data, _ } = inner;
if failed {
fail ~"Can't unwrap poisoned mutex_arc - another task failed inside!"
}
data
}
// Common code for {mutex.access,rwlock.write}{,_cond}.
#[inline(always)]
#[doc(hidden)]
@ -347,6 +365,18 @@ impl<T: const send> &rw_arc<T> {
}
}
// FIXME(#2585) make this a by-move method on the arc
#[cfg(stage1)]
fn unwrap_rw_arc<T: const send>(+arc: rw_arc<T>) -> T {
let rw_arc { x: x, _ } = arc;
let inner = unsafe { unwrap_shared_mutable_state(x) };
let rw_arc_inner { failed: failed, data: data, _ } = inner;
if failed {
fail ~"Can't unwrap poisoned rw_arc - another task failed inside!"
}
data
}
// Borrowck rightly complains about immutably aliasing the rwlock in order to
// lock it. This wraps the unsafety, with the justification that the 'lock'
// field is never overwritten; only 'failed' and 'data'.
@ -497,6 +527,22 @@ mod tests {
}
}
#[test] #[should_fail] #[ignore(cfg(windows))]
#[cfg(stage1)]
fn test_mutex_arc_unwrap_poison() {
let arc = mutex_arc(1);
let arc2 = ~(&arc).clone();
let (c,p) = pipes::stream();
do task::spawn {
do arc2.access |one| {
c.send(());
assert *one == 2;
}
}
let _ = p.recv();
let one = unwrap_mutex_arc(arc);
assert one == 1;
}
#[test] #[should_fail] #[ignore(cfg(windows))]
fn test_rw_arc_poison_wr() {
let arc = ~rw_arc(1);
let arc2 = ~arc.clone();