Skip to content

Commit

Permalink
fix owned
Browse files Browse the repository at this point in the history
Signed-off-by: Zahari Dichev <zaharidichev@gmail.com>
  • Loading branch information
zaharidichev committed Mar 25, 2021
1 parent b97b7bc commit a202d2c
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 5 deletions.
6 changes: 4 additions & 2 deletions tokio/src/sync/rwlock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -554,12 +554,13 @@ impl<T: ?Sized> RwLock<T> {
///}
/// ```
pub async fn write_owned(self: Arc<Self>) -> OwnedRwLockWriteGuard<T> {
self.s.acquire(MAX_READS as u32).await.unwrap_or_else(|_| {
self.s.acquire(self.mr).await.unwrap_or_else(|_| {
// The semaphore was closed. but, we never explicitly close it, and we have a
// handle to it through the Arc, which means that this can never happen.
unreachable!()
});
OwnedRwLockWriteGuard {
permits_acquired: self.mr,
data: self.c.get(),
lock: ManuallyDrop::new(self),
_p: PhantomData,
Expand Down Expand Up @@ -635,13 +636,14 @@ impl<T: ?Sized> RwLock<T> {
/// }
/// ```
pub fn try_write_owned(self: Arc<Self>) -> Result<OwnedRwLockWriteGuard<T>, TryLockError> {
match self.s.try_acquire(MAX_READS as u32) {
match self.s.try_acquire(self.mr) {
Ok(permit) => permit,
Err(TryAcquireError::NoPermits) => return Err(TryLockError(())),
Err(TryAcquireError::Closed) => unreachable!(),
}

Ok(OwnedRwLockWriteGuard {
permits_acquired: self.mr,
data: self.c.get(),
lock: ManuallyDrop::new(self),
_p: PhantomData,
Expand Down
9 changes: 7 additions & 2 deletions tokio/src/sync/rwlock/owned_write_guard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use std::sync::Arc;
/// [`write_owned`]: method@crate::sync::RwLock::write_owned
/// [`RwLock`]: struct@crate::sync::RwLock
pub struct OwnedRwLockWriteGuard<T: ?Sized> {
pub(super) permits_acquired: u32,
// ManuallyDrop allows us to destructure into this field without running the destructor.
pub(super) lock: ManuallyDrop<Arc<RwLock<T>>>,
pub(super) data: *mut T,
Expand Down Expand Up @@ -62,9 +63,11 @@ impl<T: ?Sized> OwnedRwLockWriteGuard<T> {
{
let data = f(&mut *this) as *mut U;
let lock = unsafe { ManuallyDrop::take(&mut this.lock) };
let permits_acquired = this.permits_acquired;
// NB: Forget to avoid drop impl from being called.
mem::forget(this);
OwnedRwLockMappedWriteGuard {
permits_acquired,
lock: ManuallyDrop::new(lock),
data,
_p: PhantomData,
Expand Down Expand Up @@ -118,10 +121,12 @@ impl<T: ?Sized> OwnedRwLockWriteGuard<T> {
Some(data) => data as *mut U,
None => return Err(this),
};
let permits_acquired = this.permits_acquired;
let lock = unsafe { ManuallyDrop::take(&mut this.lock) };
// NB: Forget to avoid drop impl from being called.
mem::forget(this);
Ok(OwnedRwLockMappedWriteGuard {
permits_acquired,
lock: ManuallyDrop::new(lock),
data,
_p: PhantomData,
Expand Down Expand Up @@ -178,7 +183,7 @@ impl<T: ?Sized> OwnedRwLockWriteGuard<T> {
let data = self.data;

// Release all but one of the permits held by the write guard
lock.s.release(super::MAX_READS - 1);
lock.s.release((self.permits_acquired - 1) as usize);
// NB: Forget to avoid drop impl from being called.
mem::forget(self);
OwnedRwLockReadGuard {
Expand Down Expand Up @@ -223,7 +228,7 @@ where

impl<T: ?Sized> Drop for OwnedRwLockWriteGuard<T> {
fn drop(&mut self) {
self.lock.s.release(super::MAX_READS);
self.lock.s.release(self.permits_acquired as usize);
unsafe { ManuallyDrop::drop(&mut self.lock) };
}
}
7 changes: 6 additions & 1 deletion tokio/src/sync/rwlock/owned_write_guard_mapped.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use std::sync::Arc;
/// [mapping]: method@crate::sync::OwnedRwLockWriteGuard::map
/// [`OwnedRwLockWriteGuard`]: struct@crate::sync::OwnedRwLockWriteGuard
pub struct OwnedRwLockMappedWriteGuard<T: ?Sized, U: ?Sized = T> {
pub(super) permits_acquired: u32,
// ManuallyDrop allows us to destructure into this field without running the destructor.
pub(super) lock: ManuallyDrop<Arc<RwLock<T>>>,
pub(super) data: *mut U,
Expand Down Expand Up @@ -61,9 +62,11 @@ impl<T: ?Sized, U: ?Sized> OwnedRwLockMappedWriteGuard<T, U> {
{
let data = f(&mut *this) as *mut V;
let lock = unsafe { ManuallyDrop::take(&mut this.lock) };
let permits_acquired = this.permits_acquired;
// NB: Forget to avoid drop impl from being called.
mem::forget(this);
OwnedRwLockMappedWriteGuard {
permits_acquired,
lock: ManuallyDrop::new(lock),
data,
_p: PhantomData,
Expand Down Expand Up @@ -116,9 +119,11 @@ impl<T: ?Sized, U: ?Sized> OwnedRwLockMappedWriteGuard<T, U> {
None => return Err(this),
};
let lock = unsafe { ManuallyDrop::take(&mut this.lock) };
let permits_acquired = this.permits_acquired;
// NB: Forget to avoid drop impl from being called.
mem::forget(this);
Ok(OwnedRwLockMappedWriteGuard {
permits_acquired,
lock: ManuallyDrop::new(lock),
data,
_p: PhantomData,
Expand Down Expand Up @@ -160,7 +165,7 @@ where

impl<T: ?Sized, U: ?Sized> Drop for OwnedRwLockMappedWriteGuard<T, U> {
fn drop(&mut self) {
self.lock.s.release(super::MAX_READS);
self.lock.s.release(self.permits_acquired as usize);
unsafe { ManuallyDrop::drop(&mut self.lock) };
}
}

0 comments on commit a202d2c

Please sign in to comment.