@@ -783,11 +783,11 @@ mod tests {
783
783
}
784
784
}
785
785
#[ 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 ) {
787
788
// Test mutual exclusion between readers and writers. Just like the
788
789
// mutex mutual exclusion test, a ways above.
789
790
let ( c, p) = pipes:: stream ( ) ;
790
- let x = ~rwlock ( ) ;
791
791
let x2 = ~x. clone ( ) ;
792
792
let sharedstate = ~0 ;
793
793
let ptr = ptr:: addr_of ( * sharedstate) ;
@@ -815,23 +815,22 @@ mod tests {
815
815
}
816
816
#[ test]
817
817
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) ;
822
822
}
823
823
#[ test]
824
824
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) ;
829
829
}
830
830
#[ 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 ) {
833
833
// Much like sem_multi_resource.
834
- let x = ~rwlock ( ) ;
835
834
let x2 = ~x. clone ( ) ;
836
835
let ( c1, p1) = pipes:: stream ( ) ;
837
836
let ( c2, p2) = pipes:: stream ( ) ;
@@ -860,14 +859,29 @@ mod tests {
860
859
}
861
860
#[ test]
862
861
fn test_rwlock_readers_and_readers ( ) {
863
- test_rwlock_handshake ( read, read, false ) ;
862
+ test_rwlock_handshake ( ~ rwlock ( ) , read, read, false ) ;
864
863
// The downgrader needs to get in before the reader gets in, otherwise
865
864
// 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 ) ;
868
867
// Two downgrade_reads can never both end up reading at the same time.
869
868
}
870
869
#[ 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]
871
885
fn test_rwlock_cond_wait ( ) {
872
886
// As test_mutex_cond_wait above.
873
887
let x = ~rwlock ( ) ;
@@ -902,6 +916,53 @@ mod tests {
902
916
let _ = port. recv ( ) ; // Wait until child wakes up
903
917
do x. read { } // Just for good measure
904
918
}
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
+ }
905
966
#[ cfg( test) ] #[ ignore( cfg( windows) ) ]
906
967
fn rwlock_kill_helper ( mode1 : rwlock_mode , mode2 : rwlock_mode ) {
907
968
// Mutex must get automatically unlocked if failed/killed within.
@@ -925,6 +986,21 @@ mod tests {
925
986
fn test_rwlock_reader_killed_reader ( ) { rwlock_kill_helper ( read, read ) ; }
926
987
#[ test] #[ ignore( cfg( windows) ) ]
927
988
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
+ }
928
1004
#[ test] #[ should_fail] #[ ignore( cfg( windows) ) ]
929
1005
fn test_rwlock_downgrade_cant_swap ( ) {
930
1006
// Tests that you can't downgrade with a different rwlock's token.
0 commit comments