@@ -3,8 +3,8 @@ use rand::Rng;
3
3
use crate :: sync:: atomic:: { AtomicUsize , Ordering } ;
4
4
use crate :: sync:: mpsc:: channel;
5
5
use crate :: sync:: {
6
- Arc , Barrier , MappedRwLockReadGuard , MappedRwLockWriteGuard , RwLock , RwLockReadGuard ,
7
- RwLockWriteGuard , TryLockError ,
6
+ Arc , MappedRwLockReadGuard , MappedRwLockWriteGuard , RwLock , RwLockReadGuard , RwLockWriteGuard ,
7
+ TryLockError ,
8
8
} ;
9
9
use crate :: thread;
10
10
@@ -511,57 +511,42 @@ fn test_downgrade_basic() {
511
511
}
512
512
513
513
#[ test]
514
- fn test_downgrade_readers ( ) {
515
- // This test creates 1 writing thread and `R` reader threads doing `N` iterations.
516
- const R : usize = 10 ;
517
- const N : usize = if cfg ! ( target_pointer_width = "64" ) { 100 } else { 20 } ;
514
+ fn test_downgrade_observe ( ) {
515
+ // Taken from the test `test_rwlock_downgrade` from:
516
+ // https://github.com/Amanieu/parking_lot/blob/master/src/rwlock.rs
518
517
519
- // The writer thread will constantly update the value inside the `RwLock`, and this test will
520
- // only pass if every reader observes all values between 0 and `N`.
521
- let rwlock = Arc :: new ( RwLock :: new ( 0 ) ) ;
522
- let barrier = Arc :: new ( Barrier :: new ( R + 1 ) ) ;
523
-
524
- // Create the writing thread.
525
- let r_writer = rwlock. clone ( ) ;
526
- let b_writer = barrier. clone ( ) ;
527
- thread:: spawn ( move || {
528
- for i in 0 ..N {
529
- let mut write_guard = r_writer. write ( ) . unwrap ( ) ;
530
- * write_guard = i;
518
+ const W : usize = if cfg ! ( target_pointer_width = "64" ) { 100 } else { 20 } ;
519
+ const N : usize = 100 ;
531
520
532
- let read_guard = RwLockWriteGuard :: downgrade ( write_guard ) ;
533
- assert_eq ! ( * read_guard , i ) ;
521
+ // This test spawns `W` writer threads, where each will increment a counter `N` times, ensuring
522
+ // that the value they wrote has not changed after downgrading.
534
523
535
- // Wait for all readers to observe the new value.
536
- b_writer. wait ( ) ;
537
- }
538
- } ) ;
524
+ let rw = Arc :: new ( RwLock :: new ( 0 ) ) ;
539
525
540
- for _ in 0 ..R {
541
- let rwlock = rwlock. clone ( ) ;
542
- let barrier = barrier. clone ( ) ;
543
- thread:: spawn ( move || {
544
- // Every reader thread needs to observe every value up to `N`.
545
- for i in 0 ..N {
546
- let read_guard = rwlock. read ( ) . unwrap ( ) ;
547
- assert_eq ! ( * read_guard, i) ;
548
- drop ( read_guard) ;
549
-
550
- // Wait for everyone to read and for the writer to change the value again.
551
- barrier. wait ( ) ;
552
-
553
- // Spin until the writer has changed the value.
554
- loop {
555
- let read_guard = rwlock. read ( ) . unwrap ( ) ;
556
- assert ! ( * read_guard >= i) ;
557
-
558
- if * read_guard > i {
559
- break ;
560
- }
526
+ // Spawn the writers that will do `W * N` operations and checks.
527
+ let handles: Vec < _ > = ( 0 ..W )
528
+ . map ( |_| {
529
+ let rw = rw. clone ( ) ;
530
+ thread:: spawn ( move || {
531
+ for _ in 0 ..N {
532
+ // Increment the counter.
533
+ let mut write_guard = rw. write ( ) . unwrap ( ) ;
534
+ * write_guard += 1 ;
535
+ let cur_val = * write_guard;
536
+
537
+ // Downgrade the lock to read mode, where the value protected cannot be modified.
538
+ let read_guard = RwLockWriteGuard :: downgrade ( write_guard) ;
539
+ assert_eq ! ( cur_val, * read_guard) ;
561
540
}
562
- }
563
- } ) ;
541
+ } )
542
+ } )
543
+ . collect ( ) ;
544
+
545
+ for handle in handles {
546
+ handle. join ( ) . unwrap ( ) ;
564
547
}
548
+
549
+ assert_eq ! ( * rw. read( ) . unwrap( ) , W * N ) ;
565
550
}
566
551
567
552
#[ test]
0 commit comments