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