1use crate::raw_rwlock::RawRwLock;
2
3pub type RwLock<T> = lock_api::RwLock<RawRwLock, T>;
72
73pub type RwLockReadGuard<'a, T> = lock_api::RwLockReadGuard<'a, RawRwLock, T>;
75
76pub type RwLockWriteGuard<'a, T> = lock_api::RwLockWriteGuard<'a, RawRwLock, T>;
78
79pub type MappedRwLockReadGuard<'a, T> = lock_api::MappedRwLockReadGuard<'a, RawRwLock, T>;
87
88pub type MappedRwLockWriteGuard<'a, T> = lock_api::MappedRwLockWriteGuard<'a, RawRwLock, T>;
96
97pub type RwLockUpgradableReadGuard<'a, T> = lock_api::RwLockUpgradableReadGuard<'a, RawRwLock, T>;
99
100#[cfg(test)]
101mod tests {
102 use crate::{RwLock, RwLockUpgradableReadGuard, RwLockWriteGuard};
103 use rand::RngExt;
104 use std::sync::Arc;
105 use std::sync::atomic::{AtomicUsize, Ordering};
106 use std::thread;
107
108 #[cfg(feature = "serde")]
109 use postcard::{from_bytes, to_stdvec};
110
111 #[derive(Eq, PartialEq, Debug)]
112 struct NonCopy(i32);
113
114 #[test]
115 fn smoke() {
116 let l = RwLock::new(());
117 drop(l.read());
118 drop(l.write());
119 drop(l.upgradable_read());
120 drop((l.read(), l.read()));
121 drop((l.read(), l.upgradable_read()));
122 drop(l.write());
123 }
124
125 #[test]
126 fn frob() {
127 const N: u32 = 10;
128 const M: u32 = if cfg!(miri) { 100 } else { 1000 };
129
130 let r = Arc::new(RwLock::new(()));
131
132 let mut threads = Vec::new();
133 for _ in 0..N {
134 let r = r.clone();
135 threads.push(thread::spawn(move || {
136 let mut rng = rand::rng();
137 for _ in 0..M {
138 if rng.random_bool(1.0 / N as f64) {
139 drop(r.write());
140 } else {
141 drop(r.read());
142 }
143 }
144 }));
145 }
146 for thread in threads {
147 thread.join().unwrap();
148 }
149 }
150
151 #[test]
152 fn test_rw_arc_no_poison_wr() {
153 let arc = Arc::new(RwLock::new(1));
154 let arc2 = arc.clone();
155 let _: Result<(), _> = thread::spawn(move || {
156 let _lock = arc2.write();
157 panic!();
158 })
159 .join();
160 let lock = arc.read();
161 assert_eq!(*lock, 1);
162 }
163
164 #[test]
165 fn test_rw_arc_no_poison_ww() {
166 let arc = Arc::new(RwLock::new(1));
167 let arc2 = arc.clone();
168 let _: Result<(), _> = thread::spawn(move || {
169 let _lock = arc2.write();
170 panic!();
171 })
172 .join();
173 let lock = arc.write();
174 assert_eq!(*lock, 1);
175 }
176
177 #[test]
178 fn test_rw_arc_no_poison_rr() {
179 let arc = Arc::new(RwLock::new(1));
180 let arc2 = arc.clone();
181 let _: Result<(), _> = thread::spawn(move || {
182 let _lock = arc2.read();
183 panic!();
184 })
185 .join();
186 let lock = arc.read();
187 assert_eq!(*lock, 1);
188 }
189
190 #[test]
191 fn test_rw_arc_no_poison_rw() {
192 let arc = Arc::new(RwLock::new(1));
193 let arc2 = arc.clone();
194 let _: Result<(), _> = thread::spawn(move || {
195 let _lock = arc2.read();
196 panic!()
197 })
198 .join();
199 let lock = arc.write();
200 assert_eq!(*lock, 1);
201 }
202
203 #[test]
204 fn test_ruw_arc() {
205 let arc = Arc::new(RwLock::new(0));
206 let arc2 = arc.clone();
207
208 let writer = thread::spawn(move || {
209 for _ in 0..10 {
210 let mut lock = arc2.write();
211 let tmp = *lock;
212 *lock = -1;
213 thread::yield_now();
214 *lock = tmp + 1;
215 }
216 });
217
218 let mut children = Vec::new();
219
220 for _ in 0..5 {
223 let arc3 = arc.clone();
224 children.push(thread::spawn(move || {
225 let lock = arc3.upgradable_read();
226 let tmp = *lock;
227 assert!(tmp >= 0);
228 thread::yield_now();
229 let mut lock = RwLockUpgradableReadGuard::upgrade(lock);
230 assert_eq!(tmp, *lock);
231 *lock = -1;
232 thread::yield_now();
233 *lock = tmp + 1;
234 }));
235 }
236
237 for _ in 0..5 {
239 let arc4 = arc.clone();
240 children.push(thread::spawn(move || {
241 let lock = arc4.read();
242 assert!(*lock >= 0);
243 }));
244 }
245
246 for r in children {
248 assert!(r.join().is_ok());
249 }
250
251 writer.join().unwrap();
253 let lock = arc.read();
254 assert_eq!(*lock, 15);
255 }
256
257 #[test]
258 fn test_rw_arc() {
259 let arc = Arc::new(RwLock::new(0));
260 let arc2 = arc.clone();
261
262 let writer = thread::spawn(move || {
263 let mut lock = arc2.write();
264 for _ in 0..10 {
265 let tmp = *lock;
266 *lock = -1;
267 thread::yield_now();
268 *lock = tmp + 1;
269 }
270 });
271
272 let mut children = Vec::new();
274 for _ in 0..5 {
275 let arc3 = arc.clone();
276 children.push(thread::spawn(move || {
277 let lock = arc3.read();
278 assert!(*lock >= 0);
279 }));
280 }
281
282 for r in children {
284 assert!(r.join().is_ok());
285 }
286
287 writer.join().unwrap();
289 let lock = arc.read();
290 assert_eq!(*lock, 10);
291 }
292
293 #[test]
294 fn test_rw_arc_access_in_unwind() {
295 let arc = Arc::new(RwLock::new(1));
296 let arc2 = arc.clone();
297 let _ = thread::spawn(move || {
298 struct Unwinder {
299 i: Arc<RwLock<isize>>,
300 }
301 impl Drop for Unwinder {
302 fn drop(&mut self) {
303 let mut lock = self.i.write();
304 *lock += 1;
305 }
306 }
307 let _u = Unwinder { i: arc2 };
308 panic!();
309 })
310 .join();
311 let lock = arc.read();
312 assert_eq!(*lock, 2);
313 }
314
315 #[test]
316 fn test_rwlock_unsized() {
317 let rw: &RwLock<[i32]> = &RwLock::new([1, 2, 3]);
318 {
319 let b = &mut *rw.write();
320 b[0] = 4;
321 b[2] = 5;
322 }
323 let comp: &[i32] = &[4, 2, 5];
324 assert_eq!(&*rw.read(), comp);
325 }
326
327 #[test]
328 fn test_read_with_waiting_writer() {
329 let lock = Arc::new(RwLock::new(()));
330 let reader = lock.read();
331
332 let lock2 = Arc::clone(&lock);
333 let writer = thread::spawn(move || drop(lock2.write()));
334 while !unsafe { lock.raw() }.has_parked_threads() {
335 thread::yield_now();
336 }
337
338 assert!(lock.try_read().is_none());
340
341 drop(reader);
342 writer.join().unwrap();
343 }
344
345 #[test]
346 fn test_rwlock_try_read() {
347 let lock = RwLock::new(0isize);
348 {
349 let read_guard = lock.read();
350
351 let read_result = lock.try_read();
352 assert!(
353 read_result.is_some(),
354 "try_read should succeed while read_guard is in scope"
355 );
356
357 drop(read_guard);
358 }
359 {
360 let upgrade_guard = lock.upgradable_read();
361
362 let read_result = lock.try_read();
363 assert!(
364 read_result.is_some(),
365 "try_read should succeed while upgrade_guard is in scope"
366 );
367
368 drop(upgrade_guard);
369 }
370 {
371 let write_guard = lock.write();
372
373 let read_result = lock.try_read();
374 assert!(
375 read_result.is_none(),
376 "try_read should fail while write_guard is in scope"
377 );
378
379 drop(write_guard);
380 }
381 }
382
383 #[test]
384 fn test_rwlock_try_write() {
385 let lock = RwLock::new(0isize);
386 {
387 let read_guard = lock.read();
388
389 let write_result = lock.try_write();
390 assert!(
391 write_result.is_none(),
392 "try_write should fail while read_guard is in scope"
393 );
394 assert!(lock.is_locked());
395 assert!(!lock.is_locked_exclusive());
396
397 drop(read_guard);
398 }
399 {
400 let upgrade_guard = lock.upgradable_read();
401
402 let write_result = lock.try_write();
403 assert!(
404 write_result.is_none(),
405 "try_write should fail while upgrade_guard is in scope"
406 );
407 assert!(lock.is_locked());
408 assert!(!lock.is_locked_exclusive());
409
410 drop(upgrade_guard);
411 }
412 {
413 let write_guard = lock.write();
414
415 let write_result = lock.try_write();
416 assert!(
417 write_result.is_none(),
418 "try_write should fail while write_guard is in scope"
419 );
420 assert!(lock.is_locked());
421 assert!(lock.is_locked_exclusive());
422
423 drop(write_guard);
424 }
425 }
426
427 #[test]
428 fn test_rwlock_try_upgrade() {
429 let lock = RwLock::new(0isize);
430 {
431 let read_guard = lock.read();
432
433 let upgrade_result = lock.try_upgradable_read();
434 assert!(
435 upgrade_result.is_some(),
436 "try_upgradable_read should succeed while read_guard is in scope"
437 );
438
439 drop(read_guard);
440 }
441 {
442 let upgrade_guard = lock.upgradable_read();
443
444 let upgrade_result = lock.try_upgradable_read();
445 assert!(
446 upgrade_result.is_none(),
447 "try_upgradable_read should fail while upgrade_guard is in scope"
448 );
449
450 drop(upgrade_guard);
451 }
452 {
453 let write_guard = lock.write();
454
455 let upgrade_result = lock.try_upgradable_read();
456 assert!(
457 upgrade_result.is_none(),
458 "try_upgradable should fail while write_guard is in scope"
459 );
460
461 drop(write_guard);
462 }
463 }
464
465 #[test]
466 fn test_into_inner() {
467 let m = RwLock::new(NonCopy(10));
468 assert_eq!(m.into_inner(), NonCopy(10));
469 }
470
471 #[test]
472 fn test_into_inner_drop() {
473 struct Foo(Arc<AtomicUsize>);
474 impl Drop for Foo {
475 fn drop(&mut self) {
476 self.0.fetch_add(1, Ordering::SeqCst);
477 }
478 }
479 let num_drops = Arc::new(AtomicUsize::new(0));
480 let m = RwLock::new(Foo(num_drops.clone()));
481 assert_eq!(num_drops.load(Ordering::SeqCst), 0);
482 {
483 let _inner = m.into_inner();
484 assert_eq!(num_drops.load(Ordering::SeqCst), 0);
485 }
486 assert_eq!(num_drops.load(Ordering::SeqCst), 1);
487 }
488
489 #[test]
490 fn test_get_mut() {
491 let mut m = RwLock::new(NonCopy(10));
492 *m.get_mut() = NonCopy(20);
493 assert_eq!(m.into_inner(), NonCopy(20));
494 }
495
496 #[test]
497 fn test_rwlockguard_sync() {
498 fn sync<T: Sync>(_: T) {}
499
500 let rwlock = RwLock::new(());
501 sync(rwlock.read());
502 sync(rwlock.write());
503 }
504
505 #[test]
506 fn test_rwlock_downgrade() {
507 let x = Arc::new(RwLock::new(0));
508 let mut handles = Vec::new();
509 for _ in 0..8 {
510 let x = x.clone();
511 handles.push(thread::spawn(move || {
512 for _ in 0..100 {
513 let mut writer = x.write();
514 *writer += 1;
515 let cur_val = *writer;
516 let reader = RwLockWriteGuard::downgrade(writer);
517 assert_eq!(cur_val, *reader);
518 }
519 }));
520 }
521 for handle in handles {
522 handle.join().unwrap()
523 }
524 assert_eq!(*x.read(), 800);
525 }
526
527 #[test]
528 fn test_rwlock_debug() {
529 let x = RwLock::new(vec![0u8, 10]);
530
531 assert_eq!(format!("{:?}", x), "RwLock { data: [0, 10] }");
532 let _lock = x.write();
533 assert_eq!(format!("{:?}", x), "RwLock { data: <locked> }");
534 }
535
536 #[test]
537 fn test_clone_through_guard() {
538 let rwlock = RwLock::new(Arc::new(1));
539 let a = rwlock.read();
540 let b = a.clone();
542 assert_eq!(Arc::strong_count(&b), 2);
543 }
544
545 #[cfg(feature = "serde")]
546 #[test]
547 fn test_serde() {
548 let contents: Vec<u8> = vec![0, 1, 2];
549 let mutex = RwLock::new(contents.clone());
550
551 let serialized = to_stdvec(&mutex).unwrap();
552 let deserialized: RwLock<Vec<u8>> = from_bytes(&serialized).unwrap();
553
554 assert_eq!(*(mutex.read()), *(deserialized.read()));
555 assert_eq!(contents, *(deserialized.read()));
556 }
557
558 #[test]
559 fn test_issue_203() {
560 struct Bar(RwLock<()>);
561
562 impl Drop for Bar {
563 fn drop(&mut self) {
564 let _n = self.0.write();
565 }
566 }
567
568 thread_local! {
569 static B: Bar = const { Bar(RwLock::new(())) };
570 }
571
572 thread::spawn(|| {
573 B.with(|_| ());
574
575 let a = RwLock::new(());
576 let _a = a.read();
577 })
578 .join()
579 .unwrap();
580 }
581
582 #[test]
583 fn test_rw_write_is_locked() {
584 let lock = RwLock::new(0isize);
585 {
586 let _read_guard = lock.read();
587
588 assert!(lock.is_locked());
589 assert!(!lock.is_locked_exclusive());
590 }
591
592 {
593 let _write_guard = lock.write();
594
595 assert!(lock.is_locked());
596 assert!(lock.is_locked_exclusive());
597 }
598 }
599
600 #[test]
601 #[cfg(feature = "arc_lock")]
602 fn test_issue_430() {
603 let lock = std::sync::Arc::new(RwLock::new(0));
604
605 let mut rl = lock.upgradable_read_arc();
606
607 rl.with_upgraded(|_| {
608 println!("lock upgrade");
609 });
610
611 rl.with_upgraded(|_| {
612 println!("lock upgrade");
613 });
614
615 drop(lock);
616 }
617}