Skip to content

Commit 6e93d67

Browse files
committed
Add more rwlock tests
1 parent 7cf21e5 commit 6e93d67

File tree

1 file changed

+92
-16
lines changed

1 file changed

+92
-16
lines changed

src/libstd/sync.rs

Lines changed: 92 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -783,11 +783,11 @@ mod tests {
783783
}
784784
}
785785
#[cfg(test)]
786-
fn test_rwlock_exclusion(mode1: rwlock_mode, mode2: rwlock_mode) {
786+
fn test_rwlock_exclusion(x: ~rwlock, mode1: rwlock_mode,
787+
mode2: rwlock_mode) {
787788
// Test mutual exclusion between readers and writers. Just like the
788789
// mutex mutual exclusion test, a ways above.
789790
let (c,p) = pipes::stream();
790-
let x = ~rwlock();
791791
let x2 = ~x.clone();
792792
let sharedstate = ~0;
793793
let ptr = ptr::addr_of(*sharedstate);
@@ -815,23 +815,22 @@ mod tests {
815815
}
816816
#[test]
817817
fn test_rwlock_readers_wont_modify_the_data() {
818-
test_rwlock_exclusion(read, write);
819-
test_rwlock_exclusion(write, read);
820-
test_rwlock_exclusion(read, downgrade);
821-
test_rwlock_exclusion(downgrade, read);
818+
test_rwlock_exclusion(~rwlock(), read, write);
819+
test_rwlock_exclusion(~rwlock(), write, read);
820+
test_rwlock_exclusion(~rwlock(), read, downgrade);
821+
test_rwlock_exclusion(~rwlock(), downgrade, read);
822822
}
823823
#[test]
824824
fn test_rwlock_writers_and_writers() {
825-
test_rwlock_exclusion(write, write);
826-
test_rwlock_exclusion(write, downgrade);
827-
test_rwlock_exclusion(downgrade, write);
828-
test_rwlock_exclusion(downgrade, downgrade);
825+
test_rwlock_exclusion(~rwlock(), write, write);
826+
test_rwlock_exclusion(~rwlock(), write, downgrade);
827+
test_rwlock_exclusion(~rwlock(), downgrade, write);
828+
test_rwlock_exclusion(~rwlock(), downgrade, downgrade);
829829
}
830830
#[cfg(test)]
831-
fn test_rwlock_handshake(mode1: rwlock_mode, mode2: rwlock_mode,
832-
make_mode2_go_first: bool) {
831+
fn test_rwlock_handshake(x: ~rwlock, mode1: rwlock_mode,
832+
mode2: rwlock_mode, make_mode2_go_first: bool) {
833833
// Much like sem_multi_resource.
834-
let x = ~rwlock();
835834
let x2 = ~x.clone();
836835
let (c1,p1) = pipes::stream();
837836
let (c2,p2) = pipes::stream();
@@ -860,14 +859,29 @@ mod tests {
860859
}
861860
#[test]
862861
fn test_rwlock_readers_and_readers() {
863-
test_rwlock_handshake(read, read, false);
862+
test_rwlock_handshake(~rwlock(), read, read, false);
864863
// The downgrader needs to get in before the reader gets in, otherwise
865864
// they cannot end up reading at the same time.
866-
test_rwlock_handshake(downgrade_read, read, false);
867-
test_rwlock_handshake(read, downgrade_read, true);
865+
test_rwlock_handshake(~rwlock(), downgrade_read, read, false);
866+
test_rwlock_handshake(~rwlock(), read, downgrade_read, true);
868867
// Two downgrade_reads can never both end up reading at the same time.
869868
}
870869
#[test]
870+
fn test_rwlock_downgrade_unlock() {
871+
// Tests that downgrade can unlock the lock in both modes
872+
let x = ~rwlock();
873+
do lock_rwlock_in_mode(x, downgrade) { }
874+
test_rwlock_handshake(x, read, read, false);
875+
let y = ~rwlock();
876+
do lock_rwlock_in_mode(y, downgrade_read) { }
877+
test_rwlock_exclusion(y, write, write);
878+
}
879+
#[test]
880+
fn test_rwlock_read_recursive() {
881+
let x = ~rwlock();
882+
do x.read { do x.read { } }
883+
}
884+
#[test]
871885
fn test_rwlock_cond_wait() {
872886
// As test_mutex_cond_wait above.
873887
let x = ~rwlock();
@@ -902,6 +916,53 @@ mod tests {
902916
let _ = port.recv(); // Wait until child wakes up
903917
do x.read { } // Just for good measure
904918
}
919+
#[cfg(test)]
920+
fn test_rwlock_cond_broadcast_helper(num_waiters: uint, dg1: bool,
921+
dg2: bool) {
922+
// Much like the mutex broadcast test. Downgrade-enabled.
923+
fn lock_cond(x: &rwlock, downgrade: bool, blk: fn(c: &condvar)) {
924+
if downgrade {
925+
do x.write_downgrade |mode| { mode.write_cond(blk) }
926+
} else {
927+
x.write_cond(blk)
928+
}
929+
}
930+
let x = ~rwlock();
931+
let mut ports = ~[];
932+
933+
for num_waiters.times {
934+
let xi = ~x.clone();
935+
let (chan, port) = pipes::stream();
936+
vec::push(ports, port);
937+
do task::spawn {
938+
do lock_cond(xi, dg1) |cond| {
939+
chan.send(());
940+
cond.wait();
941+
chan.send(());
942+
}
943+
}
944+
}
945+
946+
// wait until all children get in the mutex
947+
for ports.each |port| { let _ = port.recv(); }
948+
do lock_cond(x, dg2) |cond| {
949+
let num_woken = cond.broadcast();
950+
assert num_woken == num_waiters;
951+
}
952+
// wait until all children wake up
953+
for ports.each |port| { let _ = port.recv(); }
954+
}
955+
#[test]
956+
fn test_rwlock_cond_broadcast() {
957+
test_rwlock_cond_broadcast_helper(0, true, true);
958+
test_rwlock_cond_broadcast_helper(0, true, false);
959+
test_rwlock_cond_broadcast_helper(0, false, true);
960+
test_rwlock_cond_broadcast_helper(0, false, false);
961+
test_rwlock_cond_broadcast_helper(12, true, true);
962+
test_rwlock_cond_broadcast_helper(12, true, false);
963+
test_rwlock_cond_broadcast_helper(12, false, true);
964+
test_rwlock_cond_broadcast_helper(12, false, false);
965+
}
905966
#[cfg(test)] #[ignore(cfg(windows))]
906967
fn rwlock_kill_helper(mode1: rwlock_mode, mode2: rwlock_mode) {
907968
// Mutex must get automatically unlocked if failed/killed within.
@@ -925,6 +986,21 @@ mod tests {
925986
fn test_rwlock_reader_killed_reader() { rwlock_kill_helper(read, read ); }
926987
#[test] #[ignore(cfg(windows))]
927988
fn test_rwlock_writer_killed_writer() { rwlock_kill_helper(write,write); }
989+
#[test] #[ignore(cfg(windows))]
990+
fn test_rwlock_kill_downgrader() {
991+
rwlock_kill_helper(downgrade, read);
992+
rwlock_kill_helper(read, downgrade);
993+
rwlock_kill_helper(downgrade, write);
994+
rwlock_kill_helper(write, downgrade);
995+
rwlock_kill_helper(downgrade_read, read);
996+
rwlock_kill_helper(read, downgrade_read);
997+
rwlock_kill_helper(downgrade_read, write);
998+
rwlock_kill_helper(write, downgrade_read);
999+
rwlock_kill_helper(downgrade_read, downgrade);
1000+
rwlock_kill_helper(downgrade_read, downgrade);
1001+
rwlock_kill_helper(downgrade, downgrade_read);
1002+
rwlock_kill_helper(downgrade, downgrade_read);
1003+
}
9281004
#[test] #[should_fail] #[ignore(cfg(windows))]
9291005
fn test_rwlock_downgrade_cant_swap() {
9301006
// Tests that you can't downgrade with a different rwlock's token.

0 commit comments

Comments
 (0)