1
Fork 0

Cleanup concurrency tests

In this commit I:
- removed unneeded heap allocations
- added extra whitespace to crowded expressions
- and removed unneeded syntax
This commit is contained in:
Steven Stewart-Gallus 2013-08-31 11:26:01 -07:00
parent 89d04009c1
commit e2f2a601e8
2 changed files with 153 additions and 154 deletions

View file

@ -572,10 +572,10 @@ mod tests {
let (p, c) = comm::stream(); let (p, c) = comm::stream();
do task::spawn() || { do task::spawn {
let arc_v : Arc<~[int]> = p.recv(); let arc_v: Arc<~[int]> = p.recv();
let v = (*arc_v.get()).clone(); let v = arc_v.get().clone();
assert_eq!(v[3], 4); assert_eq!(v[3], 4);
}; };
@ -590,11 +590,11 @@ mod tests {
#[test] #[test]
fn test_mutex_arc_condvar() { fn test_mutex_arc_condvar() {
unsafe { unsafe {
let arc = ~MutexArc::new(false); let arc = MutexArc::new(false);
let arc2 = ~arc.clone(); let arc2 = arc.clone();
let (p,c) = comm::oneshot(); let (p, c) = comm::oneshot();
let (c,p) = (Cell::new(c), Cell::new(p)); let (c, p) = (Cell::new(c), Cell::new(p));
do task::spawn || { do task::spawn {
// wait until parent gets in // wait until parent gets in
p.take().recv(); p.take().recv();
do arc2.access_cond |state, cond| { do arc2.access_cond |state, cond| {
@ -615,11 +615,11 @@ mod tests {
#[test] #[should_fail] #[test] #[should_fail]
fn test_arc_condvar_poison() { fn test_arc_condvar_poison() {
unsafe { unsafe {
let arc = ~MutexArc::new(1); let arc = MutexArc::new(1);
let arc2 = ~arc.clone(); let arc2 = arc.clone();
let (p, c) = comm::stream(); let (p, c) = comm::stream();
do task::spawn_unlinked || { do task::spawn_unlinked {
let _ = p.recv(); let _ = p.recv();
do arc2.access_cond |one, cond| { do arc2.access_cond |one, cond| {
cond.signal(); cond.signal();
@ -639,9 +639,9 @@ mod tests {
#[test] #[should_fail] #[test] #[should_fail]
fn test_mutex_arc_poison() { fn test_mutex_arc_poison() {
unsafe { unsafe {
let arc = ~MutexArc::new(1); let arc = MutexArc::new(1);
let arc2 = ~arc.clone(); let arc2 = arc.clone();
do task::try || { do task::try {
do arc2.access |one| { do arc2.access |one| {
assert_eq!(*one, 2); assert_eq!(*one, 2);
} }
@ -654,7 +654,7 @@ mod tests {
#[test] #[should_fail] #[test] #[should_fail]
pub fn test_mutex_arc_unwrap_poison() { pub fn test_mutex_arc_unwrap_poison() {
let arc = MutexArc::new(1); let arc = MutexArc::new(1);
let arc2 = ~(&arc).clone(); let arc2 = arc.clone();
let (p, c) = comm::stream(); let (p, c) = comm::stream();
do task::spawn { do task::spawn {
unsafe { unsafe {
@ -670,9 +670,9 @@ mod tests {
} }
#[test] #[should_fail] #[test] #[should_fail]
fn test_rw_arc_poison_wr() { fn test_rw_arc_poison_wr() {
let arc = ~RWArc::new(1); let arc = RWArc::new(1);
let arc2 = (*arc).clone(); let arc2 = arc.clone();
do task::try || { do task::try {
do arc2.write |one| { do arc2.write |one| {
assert_eq!(*one, 2); assert_eq!(*one, 2);
} }
@ -683,9 +683,9 @@ mod tests {
} }
#[test] #[should_fail] #[test] #[should_fail]
fn test_rw_arc_poison_ww() { fn test_rw_arc_poison_ww() {
let arc = ~RWArc::new(1); let arc = RWArc::new(1);
let arc2 = (*arc).clone(); let arc2 = arc.clone();
do task::try || { do task::try {
do arc2.write |one| { do arc2.write |one| {
assert_eq!(*one, 2); assert_eq!(*one, 2);
} }
@ -696,9 +696,9 @@ mod tests {
} }
#[test] #[should_fail] #[test] #[should_fail]
fn test_rw_arc_poison_dw() { fn test_rw_arc_poison_dw() {
let arc = ~RWArc::new(1); let arc = RWArc::new(1);
let arc2 = (*arc).clone(); let arc2 = arc.clone();
do task::try || { do task::try {
do arc2.write_downgrade |mut write_mode| { do arc2.write_downgrade |mut write_mode| {
do write_mode.write |one| { do write_mode.write |one| {
assert_eq!(*one, 2); assert_eq!(*one, 2);
@ -711,9 +711,9 @@ mod tests {
} }
#[test] #[test]
fn test_rw_arc_no_poison_rr() { fn test_rw_arc_no_poison_rr() {
let arc = ~RWArc::new(1); let arc = RWArc::new(1);
let arc2 = (*arc).clone(); let arc2 = arc.clone();
do task::try || { do task::try {
do arc2.read |one| { do arc2.read |one| {
assert_eq!(*one, 2); assert_eq!(*one, 2);
} }
@ -724,9 +724,9 @@ mod tests {
} }
#[test] #[test]
fn test_rw_arc_no_poison_rw() { fn test_rw_arc_no_poison_rw() {
let arc = ~RWArc::new(1); let arc = RWArc::new(1);
let arc2 = (*arc).clone(); let arc2 = arc.clone();
do task::try || { do task::try {
do arc2.read |one| { do arc2.read |one| {
assert_eq!(*one, 2); assert_eq!(*one, 2);
} }
@ -737,12 +737,12 @@ mod tests {
} }
#[test] #[test]
fn test_rw_arc_no_poison_dr() { fn test_rw_arc_no_poison_dr() {
let arc = ~RWArc::new(1); let arc = RWArc::new(1);
let arc2 = (*arc).clone(); let arc2 = arc.clone();
do task::try || { do task::try {
do arc2.write_downgrade |write_mode| { do arc2.write_downgrade |write_mode| {
let read_mode = arc2.downgrade(write_mode); let read_mode = arc2.downgrade(write_mode);
do (&read_mode).read |one| { do read_mode.read |one| {
assert_eq!(*one, 2); assert_eq!(*one, 2);
} }
} }
@ -753,11 +753,11 @@ mod tests {
} }
#[test] #[test]
fn test_rw_arc() { fn test_rw_arc() {
let arc = ~RWArc::new(0); let arc = RWArc::new(0);
let arc2 = (*arc).clone(); let arc2 = arc.clone();
let (p,c) = comm::stream(); let (p, c) = comm::stream();
do task::spawn || { do task::spawn {
do arc2.write |num| { do arc2.write |num| {
do 10.times { do 10.times {
let tmp = *num; let tmp = *num;
@ -772,7 +772,7 @@ mod tests {
// Readers try to catch the writer in the act // Readers try to catch the writer in the act
let mut children = ~[]; let mut children = ~[];
do 5.times { do 5.times {
let arc3 = (*arc).clone(); let arc3 = arc.clone();
let mut builder = task::task(); let mut builder = task::task();
builder.future_result(|r| children.push(r)); builder.future_result(|r| children.push(r));
do builder.spawn { do builder.spawn {
@ -801,15 +801,15 @@ mod tests {
// (4) tells writer and all other readers to contend as it downgrades. // (4) tells writer and all other readers to contend as it downgrades.
// (5) Writer attempts to set state back to 42, while downgraded task // (5) Writer attempts to set state back to 42, while downgraded task
// and all reader tasks assert that it's 31337. // and all reader tasks assert that it's 31337.
let arc = ~RWArc::new(0); let arc = RWArc::new(0);
// Reader tasks // Reader tasks
let mut reader_convos = ~[]; let mut reader_convos = ~[];
do 10.times { do 10.times {
let ((rp1,rc1),(rp2,rc2)) = (comm::stream(),comm::stream()); let ((rp1, rc1), (rp2, rc2)) = (comm::stream(), comm::stream());
reader_convos.push((rc1, rp2)); reader_convos.push((rc1, rp2));
let arcn = (*arc).clone(); let arcn = arc.clone();
do task::spawn || { do task::spawn {
rp1.recv(); // wait for downgrader to give go-ahead rp1.recv(); // wait for downgrader to give go-ahead
do arcn.read |state| { do arcn.read |state| {
assert_eq!(*state, 31337); assert_eq!(*state, 31337);
@ -819,8 +819,8 @@ mod tests {
} }
// Writer task // Writer task
let arc2 = (*arc).clone(); let arc2 = arc.clone();
let ((wp1,wc1),(wp2,wc2)) = (comm::stream(),comm::stream()); let ((wp1, wc1), (wp2, wc2)) = (comm::stream(), comm::stream());
do task::spawn || { do task::spawn || {
wp1.recv(); wp1.recv();
do arc2.write_cond |state, cond| { do arc2.write_cond |state, cond| {
@ -853,7 +853,7 @@ mod tests {
} }
} }
let read_mode = arc.downgrade(write_mode); let read_mode = arc.downgrade(write_mode);
do (&read_mode).read |state| { do read_mode.read |state| {
// complete handshake with other readers // complete handshake with other readers
for &(_, ref rp) in reader_convos.iter() { for &(_, ref rp) in reader_convos.iter() {
rp.recv() rp.recv()
@ -876,11 +876,11 @@ mod tests {
// line in RWLock::write_cond() that looks like: // line in RWLock::write_cond() that looks like:
// "blk(&Condvar { order: opt_lock, ..*cond })" // "blk(&Condvar { order: opt_lock, ..*cond })"
// with just "blk(cond)". // with just "blk(cond)".
let x = ~RWArc::new(true); let x = RWArc::new(true);
let (wp, wc) = comm::stream(); let (wp, wc) = comm::stream();
// writer task // writer task
let xw = (*x).clone(); let xw = x.clone();
do task::spawn { do task::spawn {
do xw.write_cond |state, c| { do xw.write_cond |state, c| {
wc.send(()); // tell downgrader it's ok to go wc.send(()); // tell downgrader it's ok to go
@ -901,7 +901,7 @@ mod tests {
c.signal(); c.signal();
} }
// make a reader task to trigger the "reader cloud lock" handoff // make a reader task to trigger the "reader cloud lock" handoff
let xr = (*x).clone(); let xr = x.clone();
let (rp, rc) = comm::stream(); let (rp, rc) = comm::stream();
do task::spawn { do task::spawn {
rc.send(()); rc.send(());

View file

@ -691,7 +691,6 @@ impl<'self> RWLockReadMode<'self> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use sync::*; use sync::*;
use std::cast; use std::cast;
@ -705,21 +704,21 @@ mod tests {
************************************************************************/ ************************************************************************/
#[test] #[test]
fn test_sem_acquire_release() { fn test_sem_acquire_release() {
let s = ~Semaphore::new(1); let s = Semaphore::new(1);
s.acquire(); s.acquire();
s.release(); s.release();
s.acquire(); s.acquire();
} }
#[test] #[test]
fn test_sem_basic() { fn test_sem_basic() {
let s = ~Semaphore::new(1); let s = Semaphore::new(1);
do s.access { } do s.access { }
} }
#[test] #[test]
fn test_sem_as_mutex() { fn test_sem_as_mutex() {
let s = ~Semaphore::new(1); let s = Semaphore::new(1);
let s2 = ~s.clone(); let s2 = s.clone();
do task::spawn || { do task::spawn {
do s2.access { do s2.access {
do 5.times { task::deschedule(); } do 5.times { task::deschedule(); }
} }
@ -731,10 +730,10 @@ mod tests {
#[test] #[test]
fn test_sem_as_cvar() { fn test_sem_as_cvar() {
/* Child waits and parent signals */ /* Child waits and parent signals */
let (p,c) = comm::stream(); let (p, c) = comm::stream();
let s = ~Semaphore::new(0); let s = Semaphore::new(0);
let s2 = ~s.clone(); let s2 = s.clone();
do task::spawn || { do task::spawn {
s2.acquire(); s2.acquire();
c.send(()); c.send(());
} }
@ -743,10 +742,10 @@ mod tests {
let _ = p.recv(); let _ = p.recv();
/* Parent waits and child signals */ /* Parent waits and child signals */
let (p,c) = comm::stream(); let (p, c) = comm::stream();
let s = ~Semaphore::new(0); let s = Semaphore::new(0);
let s2 = ~s.clone(); let s2 = s.clone();
do task::spawn || { do task::spawn {
do 5.times { task::deschedule(); } do 5.times { task::deschedule(); }
s2.release(); s2.release();
let _ = p.recv(); let _ = p.recv();
@ -758,11 +757,11 @@ mod tests {
fn test_sem_multi_resource() { fn test_sem_multi_resource() {
// Parent and child both get in the critical section at the same // Parent and child both get in the critical section at the same
// time, and shake hands. // time, and shake hands.
let s = ~Semaphore::new(2); let s = Semaphore::new(2);
let s2 = ~s.clone(); let s2 = s.clone();
let (p1,c1) = comm::stream(); let (p1,c1) = comm::stream();
let (p2,c2) = comm::stream(); let (p2,c2) = comm::stream();
do task::spawn || { do task::spawn {
do s2.access { do s2.access {
let _ = p2.recv(); let _ = p2.recv();
c1.send(()); c1.send(());
@ -778,13 +777,13 @@ mod tests {
// Force the runtime to schedule two threads on the same sched_loop. // Force the runtime to schedule two threads on the same sched_loop.
// When one blocks, it should schedule the other one. // When one blocks, it should schedule the other one.
do task::spawn_sched(task::SingleThreaded) { do task::spawn_sched(task::SingleThreaded) {
let s = ~Semaphore::new(1); let s = Semaphore::new(1);
let s2 = ~s.clone(); let s2 = s.clone();
let (p,c) = comm::stream(); let (p, c) = comm::stream();
let child_data = Cell::new((s2, c)); let child_data = Cell::new((s2, c));
do s.access { do s.access {
let (s2, c) = child_data.take(); let (s2, c) = child_data.take();
do task::spawn || { do task::spawn {
c.send(()); c.send(());
do s2.access { } do s2.access { }
c.send(()); c.send(());
@ -802,22 +801,22 @@ mod tests {
fn test_mutex_lock() { fn test_mutex_lock() {
// Unsafely achieve shared state, and do the textbook // Unsafely achieve shared state, and do the textbook
// "load tmp = move ptr; inc tmp; store ptr <- tmp" dance. // "load tmp = move ptr; inc tmp; store ptr <- tmp" dance.
let (p,c) = comm::stream(); let (p, c) = comm::stream();
let m = ~Mutex::new(); let m = Mutex::new();
let m2 = m.clone(); let m2 = m.clone();
let mut sharedstate = ~0; let mut sharedstate = ~0;
{ {
let ptr: *int = &*sharedstate; let ptr: *int = &*sharedstate;
do task::spawn || { do task::spawn {
let sharedstate: &mut int = let sharedstate: &mut int =
unsafe { cast::transmute(ptr) }; unsafe { cast::transmute(ptr) };
access_shared(sharedstate, m2, 10); access_shared(sharedstate, &m2, 10);
c.send(()); c.send(());
} }
} }
{ {
access_shared(sharedstate, m, 10); access_shared(sharedstate, &m, 10);
let _ = p.recv(); let _ = p.recv();
assert_eq!(*sharedstate, 20); assert_eq!(*sharedstate, 20);
@ -835,12 +834,12 @@ mod tests {
} }
#[test] #[test]
fn test_mutex_cond_wait() { fn test_mutex_cond_wait() {
let m = ~Mutex::new(); let m = Mutex::new();
// Child wakes up parent // Child wakes up parent
do m.lock_cond |cond| { do m.lock_cond |cond| {
let m2 = ~m.clone(); let m2 = m.clone();
do task::spawn || { do task::spawn {
do m2.lock_cond |cond| { do m2.lock_cond |cond| {
let woken = cond.signal(); let woken = cond.signal();
assert!(woken); assert!(woken);
@ -850,8 +849,8 @@ mod tests {
} }
// Parent wakes up child // Parent wakes up child
let (port,chan) = comm::stream(); let (port,chan) = comm::stream();
let m3 = ~m.clone(); let m3 = m.clone();
do task::spawn || { do task::spawn {
do m3.lock_cond |cond| { do m3.lock_cond |cond| {
chan.send(()); chan.send(());
cond.wait(); cond.wait();
@ -867,14 +866,14 @@ mod tests {
} }
#[cfg(test)] #[cfg(test)]
fn test_mutex_cond_broadcast_helper(num_waiters: uint) { fn test_mutex_cond_broadcast_helper(num_waiters: uint) {
let m = ~Mutex::new(); let m = Mutex::new();
let mut ports = ~[]; let mut ports = ~[];
do num_waiters.times { do num_waiters.times {
let mi = ~m.clone(); let mi = m.clone();
let (port, chan) = comm::stream(); let (port, chan) = comm::stream();
ports.push(port); ports.push(port);
do task::spawn || { do task::spawn {
do mi.lock_cond |cond| { do mi.lock_cond |cond| {
chan.send(()); chan.send(());
cond.wait(); cond.wait();
@ -902,9 +901,9 @@ mod tests {
} }
#[test] #[test]
fn test_mutex_cond_no_waiter() { fn test_mutex_cond_no_waiter() {
let m = ~Mutex::new(); let m = Mutex::new();
let m2 = ~m.clone(); let m2 = m.clone();
do task::try || { do task::try {
do m.lock_cond |_x| { } do m.lock_cond |_x| { }
}; };
do m2.lock_cond |cond| { do m2.lock_cond |cond| {
@ -914,10 +913,10 @@ mod tests {
#[test] #[test]
fn test_mutex_killed_simple() { fn test_mutex_killed_simple() {
// Mutex must get automatically unlocked if failed/killed within. // Mutex must get automatically unlocked if failed/killed within.
let m = ~Mutex::new(); let m = Mutex::new();
let m2 = ~m.clone(); let m2 = m.clone();
let result: result::Result<(),()> = do task::try || { let result: result::Result<(),()> = do task::try {
do m2.lock { do m2.lock {
fail!(); fail!();
} }
@ -931,11 +930,11 @@ mod tests {
fn test_mutex_killed_cond() { fn test_mutex_killed_cond() {
// Getting killed during cond wait must not corrupt the mutex while // Getting killed during cond wait must not corrupt the mutex while
// unwinding (e.g. double unlock). // unwinding (e.g. double unlock).
let m = ~Mutex::new(); let m = Mutex::new();
let m2 = ~m.clone(); let m2 = m.clone();
let result: result::Result<(),()> = do task::try || { let result: result::Result<(),()> = do task::try {
let (p,c) = comm::stream(); let (p, c) = comm::stream();
do task::spawn || { // linked do task::spawn || { // linked
let _ = p.recv(); // wait for sibling to get in the mutex let _ = p.recv(); // wait for sibling to get in the mutex
task::deschedule(); task::deschedule();
@ -958,17 +957,17 @@ mod tests {
fn test_mutex_killed_broadcast() { fn test_mutex_killed_broadcast() {
use std::unstable::finally::Finally; use std::unstable::finally::Finally;
let m = ~Mutex::new(); let m = Mutex::new();
let m2 = ~m.clone(); let m2 = m.clone();
let (p,c) = comm::stream(); let (p, c) = comm::stream();
let result: result::Result<(),()> = do task::try || { let result: result::Result<(),()> = do task::try {
let mut sibling_convos = ~[]; let mut sibling_convos = ~[];
do 2.times { do 2.times {
let (p,c) = comm::stream(); let (p, c) = comm::stream();
let c = Cell::new(c); let c = Cell::new(c);
sibling_convos.push(p); sibling_convos.push(p);
let mi = ~m2.clone(); let mi = m2.clone();
// spawn sibling task // spawn sibling task
do task::spawn { // linked do task::spawn { // linked
do mi.lock_cond |cond| { do mi.lock_cond |cond| {
@ -1003,10 +1002,10 @@ mod tests {
#[test] #[test]
fn test_mutex_cond_signal_on_0() { fn test_mutex_cond_signal_on_0() {
// Tests that signal_on(0) is equivalent to signal(). // Tests that signal_on(0) is equivalent to signal().
let m = ~Mutex::new(); let m = Mutex::new();
do m.lock_cond |cond| { do m.lock_cond |cond| {
let m2 = ~m.clone(); let m2 = m.clone();
do task::spawn || { do task::spawn {
do m2.lock_cond |cond| { do m2.lock_cond |cond| {
cond.signal_on(0); cond.signal_on(0);
} }
@ -1017,10 +1016,10 @@ mod tests {
#[test] #[test]
fn test_mutex_different_conds() { fn test_mutex_different_conds() {
let result = do task::try { let result = do task::try {
let m = ~Mutex::new_with_condvars(2); let m = Mutex::new_with_condvars(2);
let m2 = ~m.clone(); let m2 = m.clone();
let (p,c) = comm::stream(); let (p, c) = comm::stream();
do task::spawn || { do task::spawn {
do m2.lock_cond |cond| { do m2.lock_cond |cond| {
c.send(()); c.send(());
cond.wait_on(1); cond.wait_on(1);
@ -1038,17 +1037,17 @@ mod tests {
#[test] #[test]
fn test_mutex_no_condvars() { fn test_mutex_no_condvars() {
let result = do task::try { let result = do task::try {
let m = ~Mutex::new_with_condvars(0); let m = Mutex::new_with_condvars(0);
do m.lock_cond |cond| { cond.wait(); } do m.lock_cond |cond| { cond.wait(); }
}; };
assert!(result.is_err()); assert!(result.is_err());
let result = do task::try { let result = do task::try {
let m = ~Mutex::new_with_condvars(0); let m = Mutex::new_with_condvars(0);
do m.lock_cond |cond| { cond.signal(); } do m.lock_cond |cond| { cond.signal(); }
}; };
assert!(result.is_err()); assert!(result.is_err());
let result = do task::try { let result = do task::try {
let m = ~Mutex::new_with_condvars(0); let m = Mutex::new_with_condvars(0);
do m.lock_cond |cond| { cond.broadcast(); } do m.lock_cond |cond| { cond.broadcast(); }
}; };
assert!(result.is_err()); assert!(result.is_err());
@ -1075,17 +1074,17 @@ mod tests {
} }
} }
#[cfg(test)] #[cfg(test)]
fn test_rwlock_exclusion(x: ~RWLock, fn test_rwlock_exclusion(x: &RWLock,
mode1: RWLockMode, mode1: RWLockMode,
mode2: RWLockMode) { mode2: RWLockMode) {
// Test mutual exclusion between readers and writers. Just like the // Test mutual exclusion between readers and writers. Just like the
// mutex mutual exclusion test, a ways above. // mutex mutual exclusion test, a ways above.
let (p,c) = comm::stream(); let (p, c) = comm::stream();
let x2 = (*x).clone(); let x2 = x.clone();
let mut sharedstate = ~0; let mut sharedstate = ~0;
{ {
let ptr: *int = &*sharedstate; let ptr: *int = &*sharedstate;
do task::spawn || { do task::spawn {
let sharedstate: &mut int = let sharedstate: &mut int =
unsafe { cast::transmute(ptr) }; unsafe { cast::transmute(ptr) };
access_shared(sharedstate, &x2, mode1, 10); access_shared(sharedstate, &x2, mode1, 10);
@ -1112,28 +1111,28 @@ mod tests {
} }
#[test] #[test]
fn test_rwlock_readers_wont_modify_the_data() { fn test_rwlock_readers_wont_modify_the_data() {
test_rwlock_exclusion(~RWLock::new(), Read, Write); test_rwlock_exclusion(&RWLock::new(), Read, Write);
test_rwlock_exclusion(~RWLock::new(), Write, Read); test_rwlock_exclusion(&RWLock::new(), Write, Read);
test_rwlock_exclusion(~RWLock::new(), Read, Downgrade); test_rwlock_exclusion(&RWLock::new(), Read, Downgrade);
test_rwlock_exclusion(~RWLock::new(), Downgrade, Read); test_rwlock_exclusion(&RWLock::new(), Downgrade, Read);
} }
#[test] #[test]
fn test_rwlock_writers_and_writers() { fn test_rwlock_writers_and_writers() {
test_rwlock_exclusion(~RWLock::new(), Write, Write); test_rwlock_exclusion(&RWLock::new(), Write, Write);
test_rwlock_exclusion(~RWLock::new(), Write, Downgrade); test_rwlock_exclusion(&RWLock::new(), Write, Downgrade);
test_rwlock_exclusion(~RWLock::new(), Downgrade, Write); test_rwlock_exclusion(&RWLock::new(), Downgrade, Write);
test_rwlock_exclusion(~RWLock::new(), Downgrade, Downgrade); test_rwlock_exclusion(&RWLock::new(), Downgrade, Downgrade);
} }
#[cfg(test)] #[cfg(test)]
fn test_rwlock_handshake(x: ~RWLock, fn test_rwlock_handshake(x: &RWLock,
mode1: RWLockMode, mode1: RWLockMode,
mode2: RWLockMode, mode2: RWLockMode,
make_mode2_go_first: bool) { make_mode2_go_first: bool) {
// Much like sem_multi_resource. // Much like sem_multi_resource.
let x2 = (*x).clone(); let x2 = x.clone();
let (p1,c1) = comm::stream(); let (p1, c1) = comm::stream();
let (p2,c2) = comm::stream(); let (p2, c2) = comm::stream();
do task::spawn || { do task::spawn {
if !make_mode2_go_first { if !make_mode2_go_first {
let _ = p2.recv(); // parent sends to us once it locks, or ... let _ = p2.recv(); // parent sends to us once it locks, or ...
} }
@ -1158,37 +1157,37 @@ mod tests {
} }
#[test] #[test]
fn test_rwlock_readers_and_readers() { fn test_rwlock_readers_and_readers() {
test_rwlock_handshake(~RWLock::new(), Read, Read, false); test_rwlock_handshake(&RWLock::new(), Read, Read, false);
// The downgrader needs to get in before the reader gets in, otherwise // The downgrader needs to get in before the reader gets in, otherwise
// they cannot end up reading at the same time. // they cannot end up reading at the same time.
test_rwlock_handshake(~RWLock::new(), DowngradeRead, Read, false); test_rwlock_handshake(&RWLock::new(), DowngradeRead, Read, false);
test_rwlock_handshake(~RWLock::new(), Read, DowngradeRead, true); test_rwlock_handshake(&RWLock::new(), Read, DowngradeRead, true);
// Two downgrade_reads can never both end up reading at the same time. // Two downgrade_reads can never both end up reading at the same time.
} }
#[test] #[test]
fn test_rwlock_downgrade_unlock() { fn test_rwlock_downgrade_unlock() {
// Tests that downgrade can unlock the lock in both modes // Tests that downgrade can unlock the lock in both modes
let x = ~RWLock::new(); let x = RWLock::new();
do lock_rwlock_in_mode(x, Downgrade) { } do lock_rwlock_in_mode(&x, Downgrade) { }
test_rwlock_handshake(x, Read, Read, false); test_rwlock_handshake(&x, Read, Read, false);
let y = ~RWLock::new(); let y = RWLock::new();
do lock_rwlock_in_mode(y, DowngradeRead) { } do lock_rwlock_in_mode(&y, DowngradeRead) { }
test_rwlock_exclusion(y, Write, Write); test_rwlock_exclusion(&y, Write, Write);
} }
#[test] #[test]
fn test_rwlock_read_recursive() { fn test_rwlock_read_recursive() {
let x = ~RWLock::new(); let x = RWLock::new();
do x.read { do x.read { } } do x.read { do x.read { } }
} }
#[test] #[test]
fn test_rwlock_cond_wait() { fn test_rwlock_cond_wait() {
// As test_mutex_cond_wait above. // As test_mutex_cond_wait above.
let x = ~RWLock::new(); let x = RWLock::new();
// Child wakes up parent // Child wakes up parent
do x.write_cond |cond| { do x.write_cond |cond| {
let x2 = (*x).clone(); let x2 = x.clone();
do task::spawn || { do task::spawn {
do x2.write_cond |cond| { do x2.write_cond |cond| {
let woken = cond.signal(); let woken = cond.signal();
assert!(woken); assert!(woken);
@ -1197,9 +1196,9 @@ mod tests {
cond.wait(); cond.wait();
} }
// Parent wakes up child // Parent wakes up child
let (port,chan) = comm::stream(); let (port, chan) = comm::stream();
let x3 = (*x).clone(); let x3 = x.clone();
do task::spawn || { do task::spawn {
do x3.write_cond |cond| { do x3.write_cond |cond| {
chan.send(()); chan.send(());
cond.wait(); cond.wait();
@ -1229,14 +1228,14 @@ mod tests {
do x.write_cond |c| { blk(c) } do x.write_cond |c| { blk(c) }
} }
} }
let x = ~RWLock::new(); let x = RWLock::new();
let mut ports = ~[]; let mut ports = ~[];
do num_waiters.times { do num_waiters.times {
let xi = (*x).clone(); let xi = x.clone();
let (port, chan) = comm::stream(); let (port, chan) = comm::stream();
ports.push(port); ports.push(port);
do task::spawn || { do task::spawn {
do lock_cond(&xi, dg1) |cond| { do lock_cond(&xi, dg1) |cond| {
chan.send(()); chan.send(());
cond.wait(); cond.wait();
@ -1247,7 +1246,7 @@ mod tests {
// wait until all children get in the mutex // wait until all children get in the mutex
for port in ports.iter() { let _ = port.recv(); } for port in ports.iter() { let _ = port.recv(); }
do lock_cond(x, dg2) |cond| { do lock_cond(&x, dg2) |cond| {
let num_woken = cond.broadcast(); let num_woken = cond.broadcast();
assert_eq!(num_woken, num_waiters); assert_eq!(num_woken, num_waiters);
} }
@ -1268,8 +1267,8 @@ mod tests {
#[cfg(test)] #[cfg(test)]
fn rwlock_kill_helper(mode1: RWLockMode, mode2: RWLockMode) { fn rwlock_kill_helper(mode1: RWLockMode, mode2: RWLockMode) {
// Mutex must get automatically unlocked if failed/killed within. // Mutex must get automatically unlocked if failed/killed within.
let x = ~RWLock::new(); let x = RWLock::new();
let x2 = (*x).clone(); let x2 = x.clone();
let result: result::Result<(),()> = do task::try || { let result: result::Result<(),()> = do task::try || {
do lock_rwlock_in_mode(&x2, mode1) { do lock_rwlock_in_mode(&x2, mode1) {
@ -1278,7 +1277,7 @@ mod tests {
}; };
assert!(result.is_err()); assert!(result.is_err());
// child task must have finished by the time try returns // child task must have finished by the time try returns
do lock_rwlock_in_mode(x, mode2) { } do lock_rwlock_in_mode(&x, mode2) { }
} }
#[test] #[test]
fn test_rwlock_reader_killed_writer() { fn test_rwlock_reader_killed_writer() {
@ -1286,15 +1285,15 @@ mod tests {
} }
#[test] #[test]
fn test_rwlock_writer_killed_reader() { fn test_rwlock_writer_killed_reader() {
rwlock_kill_helper(Write,Read ); rwlock_kill_helper(Write, Read);
} }
#[test] #[test]
fn test_rwlock_reader_killed_reader() { fn test_rwlock_reader_killed_reader() {
rwlock_kill_helper(Read, Read ); rwlock_kill_helper(Read, Read);
} }
#[test] #[test]
fn test_rwlock_writer_killed_writer() { fn test_rwlock_writer_killed_writer() {
rwlock_kill_helper(Write,Write); rwlock_kill_helper(Write, Write);
} }
#[test] #[test]
fn test_rwlock_kill_downgrader() { fn test_rwlock_kill_downgrader() {
@ -1314,8 +1313,8 @@ mod tests {
#[test] #[should_fail] #[test] #[should_fail]
fn test_rwlock_downgrade_cant_swap() { fn test_rwlock_downgrade_cant_swap() {
// Tests that you can't downgrade with a different rwlock's token. // Tests that you can't downgrade with a different rwlock's token.
let x = ~RWLock::new(); let x = RWLock::new();
let y = ~RWLock::new(); let y = RWLock::new();
do x.write_downgrade |xwrite| { do x.write_downgrade |xwrite| {
let mut xopt = Some(xwrite); let mut xopt = Some(xwrite);
do y.write_downgrade |_ywrite| { do y.write_downgrade |_ywrite| {