diff options
author | Zahari Dichev <zaharidichev@gmail.com> | 2020-10-23 20:07:00 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-10-23 10:07:00 -0700 |
commit | e804f88d60071f0d89db85aaa4a073857904b545 (patch) | |
tree | 2450fdc093b9f361573febc7f7ca22b0275ae1c6 /tokio/src/sync/tests/loom_rwlock.rs | |
parent | c1539132110d3f8d20d22efb4b3f6a16fafd0e63 (diff) |
sync: add mem::forget to RwLockWriteGuard::downgrade. (#2957)
Currently when `RwLockWriteGuard::downgrade` the `MAX_READS - 1`
permits are added to the semaphore. When `RwLockWriteGuard::drop`
gets invoked however another `MAX_READS` permits are added. This
results in releasing more permits that were actually aquired when
downgrading a write to a read lock. This is why we need to call
`mem::forget` on the `RwLockWriteGuard` in order to avoid
invoking the destructor.
Fixes: #2941
Diffstat (limited to 'tokio/src/sync/tests/loom_rwlock.rs')
-rw-r--r-- | tokio/src/sync/tests/loom_rwlock.rs | 25 |
1 files changed, 23 insertions, 2 deletions
diff --git a/tokio/src/sync/tests/loom_rwlock.rs b/tokio/src/sync/tests/loom_rwlock.rs index 48d06e1d..2834a263 100644 --- a/tokio/src/sync/tests/loom_rwlock.rs +++ b/tokio/src/sync/tests/loom_rwlock.rs @@ -6,7 +6,7 @@ use std::sync::Arc; #[test] fn concurrent_write() { - let mut b = loom::model::Builder::new(); + let b = loom::model::Builder::new(); b.check(|| { let rwlock = Arc::new(RwLock::<u32>::new(0)); @@ -37,7 +37,7 @@ fn concurrent_write() { #[test] fn concurrent_read_write() { - let mut b = loom::model::Builder::new(); + let b = loom::model::Builder::new(); b.check(|| { let rwlock = Arc::new(RwLock::<u32>::new(0)); @@ -76,3 +76,24 @@ fn concurrent_read_write() { assert_eq!(10, *guard); }); } +#[test] +fn downgrade() { + loom::model(|| { + let lock = Arc::new(RwLock::new(1)); + + let n = block_on(lock.write()); + + let cloned_lock = lock.clone(); + let handle = thread::spawn(move || { + let mut guard = block_on(cloned_lock.write()); + *guard = 2; + }); + + let n = n.downgrade(); + assert_eq!(*n, 1); + + drop(n); + handle.join().unwrap(); + assert_eq!(*block_on(lock.read()), 2); + }); +} |