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()8 fn 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()39 fn 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()86 fn 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