1 use crate::sync::rwlock::*; 2 3 use loom::future::block_on; 4 use loom::thread; 5 use std::sync::Arc; 6 7 #[test] concurrent_write()8fn concurrent_write() { 9 let b = loom::model::Builder::new(); 10 11 b.check(|| { 12 let rwlock = Arc::new(RwLock::<u32>::new(0)); 13 14 let rwclone = rwlock.clone(); 15 let t1 = thread::spawn(move || { 16 block_on(async { 17 let mut guard = rwclone.write().await; 18 *guard += 5; 19 }); 20 }); 21 22 let rwclone = rwlock.clone(); 23 let t2 = thread::spawn(move || { 24 block_on(async { 25 let mut guard = rwclone.write_owned().await; 26 *guard += 5; 27 }); 28 }); 29 30 t1.join().expect("thread 1 write should not panic"); 31 t2.join().expect("thread 2 write should not panic"); 32 //when all threads have finished the value on the lock should be 10 33 let guard = block_on(rwlock.read()); 34 assert_eq!(10, *guard); 35 }); 36 } 37 38 #[test] concurrent_read_write()39fn concurrent_read_write() { 40 let b = loom::model::Builder::new(); 41 42 b.check(|| { 43 let rwlock = Arc::new(RwLock::<u32>::new(0)); 44 45 let rwclone = rwlock.clone(); 46 let t1 = thread::spawn(move || { 47 block_on(async { 48 let mut guard = rwclone.write().await; 49 *guard += 5; 50 }); 51 }); 52 53 let rwclone = rwlock.clone(); 54 let t2 = thread::spawn(move || { 55 block_on(async { 56 let mut guard = rwclone.write_owned().await; 57 *guard += 5; 58 }); 59 }); 60 61 let rwclone = rwlock.clone(); 62 let t3 = thread::spawn(move || { 63 block_on(async { 64 let guard = rwclone.read().await; 65 //at this state the value on the lock may either be 0, 5, or 10 66 assert!(*guard == 0 || *guard == 5 || *guard == 10); 67 }); 68 }); 69 70 { 71 let guard = block_on(rwlock.clone().read_owned()); 72 //at this state the value on the lock may either be 0, 5, or 10 73 assert!(*guard == 0 || *guard == 5 || *guard == 10); 74 } 75 76 t1.join().expect("thread 1 write should not panic"); 77 t2.join().expect("thread 2 write should not panic"); 78 t3.join().expect("thread 3 read should not panic"); 79 80 let guard = block_on(rwlock.read()); 81 //when all threads have finished the value on the lock should be 10 82 assert_eq!(10, *guard); 83 }); 84 } 85 #[test] downgrade()86fn downgrade() { 87 loom::model(|| { 88 let lock = Arc::new(RwLock::new(1)); 89 90 let n = block_on(lock.write()); 91 92 let cloned_lock = lock.clone(); 93 let handle = thread::spawn(move || { 94 let mut guard = block_on(cloned_lock.write()); 95 *guard = 2; 96 }); 97 98 let n = n.downgrade(); 99 assert_eq!(*n, 1); 100 101 drop(n); 102 handle.join().unwrap(); 103 assert_eq!(*block_on(lock.read()), 2); 104 }); 105 } 106