From f20d2df2eb44e926718e8741798adb04370911ff Mon Sep 17 00:00:00 2001 From: Samuel Onoja Date: Tue, 14 May 2024 22:19:45 +0100 Subject: [PATCH 1/4] save dev state --- futures-util/src/lock/mutex.rs | 128 +++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) diff --git a/futures-util/src/lock/mutex.rs b/futures-util/src/lock/mutex.rs index 79272f4be..a8ebb9241 100644 --- a/futures-util/src/lock/mutex.rs +++ b/futures-util/src/lock/mutex.rs @@ -1,3 +1,4 @@ +use core::ptr; use std::cell::UnsafeCell; use std::marker::PhantomData; use std::ops::{Deref, DerefMut}; @@ -283,6 +284,46 @@ pub struct OwnedMutexGuard { mutex: Arc>, } +impl OwnedMutexGuard { + /// `skip_drop` prevents the `OwnedMutexGuard` from being automatically dropped, allowing manual control over the drop process. + /// This method returns an `OwnedMutexGuardMutex` which contains the original `Arc>`. + fn skip_drop(self) -> OwnedMutexGuardMutex { + // Prevents automatic drop by wrapping in `ManuallyDrop` + let man = mem::ManuallyDrop::new(self); + // Unsafely reads the `Arc>` from the `ManuallyDrop` wrapper + OwnedMutexGuardMutex { mutex: unsafe { ptr::read(&man.mutex) } } + } + + /// `OwnedMutexGuard::map` allows transforming the inner value of the `OwnedMutexGuard` using a provided closure. + /// The transformation is done in-place, returning a new `OwnedMappedMutexGuard` with the mapped value. + #[inline] + pub fn map(mut this: Self, f: F) -> OwnedMappedMutexGuard + where + U: ?Sized, + F: FnOnce(&mut T) -> &mut U, + { + let value = f(&mut *this) as *mut U; + let mutex = this.skip_drop(); + OwnedMappedMutexGuard { value, mutex: mutex.mutex } + } + + /// `OwnedMutexGuard::try_map` attempts to transform the inner value of the `OwnedMutexGuard` using a provided closure. + /// If the closure returns `None`, the original `OwnedMutexGuard` is returned. + #[inline] + pub fn try_map(mut this: Self, f: F) -> Result, Self> + where + U: ?Sized, + F: FnOnce(&mut T) -> Option<&mut U>, + { + let value = match f(&mut *this) { + Some(data) => data as *mut U, + None => return Err(this), + }; + let mutex = this.skip_drop(); + Ok(OwnedMappedMutexGuard { value, mutex: mutex.mutex }) + } +} + impl fmt::Debug for OwnedMutexGuard { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("OwnedMutexGuard") @@ -311,6 +352,47 @@ impl DerefMut for OwnedMutexGuard { } } +/// An RAII guard returned by the `OwnedMutexGuard::map` and `OwnedMappedMutexGuard::map` methods. +/// When this structure is dropped (falls out of scope), the lock will be unlocked. +pub struct OwnedMappedMutexGuard { + value: *mut U, + mutex: Arc>, +} + +/// A owned handle to a held `Mutex`. +struct OwnedMappedMutexGuardExt { + value: *mut U, + mutex: Arc>, +} + +impl OwnedMappedMutexGuard { + /// `skip_drop` prevents the `OwnedMutexGuard` from being automatically dropped, allowing manual control over the drop process. + /// This method returns an `OwnedMutexGuardMutex` which contains the original `Arc>`. + fn skip_drop(self) -> OwnedMappedMutexGuardExt { + // Prevents automatic drop by wrapping in `ManuallyDrop` + let selfi = mem::ManuallyDrop::new(self); + // Unsafely reads the `Arc>` from the `ManuallyDrop` wrapper + OwnedMappedMutexGuardExt { mutex: unsafe { ptr::read(&selfi.mutex) }, value: selfi.value } + } + + /// `OwnedMutexGuard::map` allows transforming the inner value of the `OwnedMutexGuard` using a provided closure. + /// The transformation is done in-place, returning a new `OwnedMappedMutexGuard` with the mapped value. + #[inline] + pub fn map(mut this: Self, f: F) -> OwnedMappedMutexGuard + where + F: FnOnce(&mut U) -> &mut C, + { + let value = f(&mut *this) as *mut ; + let mutex = this.skip_drop(); + OwnedMappedMutexGuard { value, mutex: mutex.mutex } + } +} + +/// A owned handle to a held `Mutex`. +struct OwnedMutexGuardMutex { + mutex: Arc>, +} + /// A future which resolves when the target mutex has been successfully acquired. pub struct MutexLockFuture<'a, T: ?Sized> { // `None` indicates that the mutex was successfully acquired. @@ -544,6 +626,52 @@ unsafe impl Sync for OwnedMutexGuard {} unsafe impl Send for MappedMutexGuard<'_, T, U> {} unsafe impl Sync for MappedMutexGuard<'_, T, U> {} +impl Drop for OwnedMappedMutexGuard { + fn drop(&mut self) { + self.mutex.unlock() + } +} + +unsafe impl Sync for OwnedMappedMutexGuard +where + T: ?Sized + Send + Sync, + U: ?Sized + Send + Sync, +{ +} +unsafe impl Send for OwnedMappedMutexGuard +where + T: ?Sized + Send, + U: ?Sized + Send, +{ +} + +impl Deref for OwnedMappedMutexGuard { + type Target = U; + /// Deref implementation to allow access to the mapped value. + fn deref(&self) -> &Self::Target { + unsafe { &*self.value } + } +} + +impl DerefMut for OwnedMappedMutexGuard { + /// DerefMut implementation to allow mutable access to the mapped value. + fn deref_mut(&mut self) -> &mut Self::Target { + unsafe { &mut *self.value } + } +} + +impl fmt::Debug for OwnedMappedMutexGuard { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&**self, f) + } +} + +impl fmt::Display for OwnedMappedMutexGuard { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(&**self, f) + } +} + #[cfg(test)] mod tests { use super::*; From 8f51b16cf7a26c6067611f449d8c9ad1179a811f Mon Sep 17 00:00:00 2001 From: Samuel Onoja Date: Tue, 14 May 2024 22:23:28 +0100 Subject: [PATCH 2/4] fix type parameter error --- futures-util/src/lock/mutex.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/futures-util/src/lock/mutex.rs b/futures-util/src/lock/mutex.rs index a8ebb9241..a0176c72a 100644 --- a/futures-util/src/lock/mutex.rs +++ b/futures-util/src/lock/mutex.rs @@ -289,9 +289,9 @@ impl OwnedMutexGuard { /// This method returns an `OwnedMutexGuardMutex` which contains the original `Arc>`. fn skip_drop(self) -> OwnedMutexGuardMutex { // Prevents automatic drop by wrapping in `ManuallyDrop` - let man = mem::ManuallyDrop::new(self); + let selfi = mem::ManuallyDrop::new(self); // Unsafely reads the `Arc>` from the `ManuallyDrop` wrapper - OwnedMutexGuardMutex { mutex: unsafe { ptr::read(&man.mutex) } } + OwnedMutexGuardMutex { mutex: unsafe { ptr::read(&selfi.mutex) } } } /// `OwnedMutexGuard::map` allows transforming the inner value of the `OwnedMutexGuard` using a provided closure. @@ -382,7 +382,7 @@ impl OwnedMappedMutexGuard { where F: FnOnce(&mut U) -> &mut C, { - let value = f(&mut *this) as *mut ; + let value = f(&mut *this) as *mut C; let mutex = this.skip_drop(); OwnedMappedMutexGuard { value, mutex: mutex.mutex } } From a7ab96c4bb736ca2c4005d7740819d56a867b679 Mon Sep 17 00:00:00 2001 From: Samuel Onoja Date: Tue, 14 May 2024 22:58:05 +0100 Subject: [PATCH 3/4] implement map and try_map for OwnedMappedMutexGuard --- futures-util/src/lock/mutex.rs | 56 ++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 19 deletions(-) diff --git a/futures-util/src/lock/mutex.rs b/futures-util/src/lock/mutex.rs index a0176c72a..8ea4526bc 100644 --- a/futures-util/src/lock/mutex.rs +++ b/futures-util/src/lock/mutex.rs @@ -284,18 +284,22 @@ pub struct OwnedMutexGuard { mutex: Arc>, } +/// A owned handle to a held `Mutex`. +struct OwnedMutexGuardExtendedLock { + mutex: Arc>, +} + impl OwnedMutexGuard { /// `skip_drop` prevents the `OwnedMutexGuard` from being automatically dropped, allowing manual control over the drop process. - /// This method returns an `OwnedMutexGuardMutex` which contains the original `Arc>`. - fn skip_drop(self) -> OwnedMutexGuardMutex { + /// This method returns an `OwnedMutexGuardExtendedLock` which contains the original `Arc>`. + fn skip_drop(self) -> OwnedMutexGuardExtendedLock { // Prevents automatic drop by wrapping in `ManuallyDrop` - let selfi = mem::ManuallyDrop::new(self); + let man = mem::ManuallyDrop::new(self); // Unsafely reads the `Arc>` from the `ManuallyDrop` wrapper - OwnedMutexGuardMutex { mutex: unsafe { ptr::read(&selfi.mutex) } } + OwnedMutexGuardExtendedLock { mutex: unsafe { ptr::read(&man.mutex) } } } - /// `OwnedMutexGuard::map` allows transforming the inner value of the `OwnedMutexGuard` using a provided closure. - /// The transformation is done in-place, returning a new `OwnedMappedMutexGuard` with the mapped value. + /// Returns a locked view over a portion of the locked data. #[inline] pub fn map(mut this: Self, f: F) -> OwnedMappedMutexGuard where @@ -307,8 +311,8 @@ impl OwnedMutexGuard { OwnedMappedMutexGuard { value, mutex: mutex.mutex } } - /// `OwnedMutexGuard::try_map` attempts to transform the inner value of the `OwnedMutexGuard` using a provided closure. - /// If the closure returns `None`, the original `OwnedMutexGuard` is returned. + /// Returns a locked view over a portion of the locked data. + /// If the closure returns `None`, the original `OwnedMappedMutexGuard` is returned. #[inline] pub fn try_map(mut this: Self, f: F) -> Result, Self> where @@ -320,6 +324,7 @@ impl OwnedMutexGuard { None => return Err(this), }; let mutex = this.skip_drop(); + Ok(OwnedMappedMutexGuard { value, mutex: mutex.mutex }) } } @@ -360,23 +365,25 @@ pub struct OwnedMappedMutexGuard { } /// A owned handle to a held `Mutex`. -struct OwnedMappedMutexGuardExt { - value: *mut U, +struct OwnedMappedMutexGuardExtendedLock { + _value: *mut U, mutex: Arc>, } impl OwnedMappedMutexGuard { /// `skip_drop` prevents the `OwnedMutexGuard` from being automatically dropped, allowing manual control over the drop process. - /// This method returns an `OwnedMutexGuardMutex` which contains the original `Arc>`. - fn skip_drop(self) -> OwnedMappedMutexGuardExt { + /// This method returns an `OwnedMappedMutexGuardExtendedLock` which contains the original `Arc>`. + fn skip_drop(self) -> OwnedMappedMutexGuardExtendedLock { // Prevents automatic drop by wrapping in `ManuallyDrop` let selfi = mem::ManuallyDrop::new(self); // Unsafely reads the `Arc>` from the `ManuallyDrop` wrapper - OwnedMappedMutexGuardExt { mutex: unsafe { ptr::read(&selfi.mutex) }, value: selfi.value } + OwnedMappedMutexGuardExtendedLock { + mutex: unsafe { ptr::read(&selfi.mutex) }, + _value: selfi.value, + } } - /// `OwnedMutexGuard::map` allows transforming the inner value of the `OwnedMutexGuard` using a provided closure. - /// The transformation is done in-place, returning a new `OwnedMappedMutexGuard` with the mapped value. + /// Returns a locked view over a portion of the locked data. #[inline] pub fn map(mut this: Self, f: F) -> OwnedMappedMutexGuard where @@ -386,11 +393,22 @@ impl OwnedMappedMutexGuard { let mutex = this.skip_drop(); OwnedMappedMutexGuard { value, mutex: mutex.mutex } } -} -/// A owned handle to a held `Mutex`. -struct OwnedMutexGuardMutex { - mutex: Arc>, + /// Returns a locked view over a portion of the locked data. + /// If the closure returns `None`, the original `OwnedMappedMutexGuard` is returned. + #[inline] + pub fn try_map(mut this: Self, f: F) -> Result, Self> + where + F: FnOnce(&mut U) -> Option<&mut C>, + { + let value = match f(&mut *this) { + Some(data) => data as *mut C, + None => return Err(this), + }; + let mutex = this.skip_drop(); + + Ok(OwnedMappedMutexGuard { value, mutex: mutex.mutex }) + } } /// A future which resolves when the target mutex has been successfully acquired. From ab074f8acd1002d4bc11399136f45dc651e83793 Mon Sep 17 00:00:00 2001 From: Samuel Onoja Date: Wed, 15 May 2024 03:19:06 +0100 Subject: [PATCH 4/4] export OwnedMappedMutexGuard --- futures-util/src/lock/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/futures-util/src/lock/mod.rs b/futures-util/src/lock/mod.rs index 8ca0ff625..4b7d9f06a 100644 --- a/futures-util/src/lock/mod.rs +++ b/futures-util/src/lock/mod.rs @@ -14,7 +14,8 @@ pub use self::bilock::{BiLock, BiLockAcquire, BiLockGuard, ReuniteError}; #[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] #[cfg(feature = "std")] pub use self::mutex::{ - MappedMutexGuard, Mutex, MutexGuard, MutexLockFuture, OwnedMutexGuard, OwnedMutexLockFuture, + MappedMutexGuard, Mutex, MutexGuard, MutexLockFuture, OwnedMappedMutexGuard, OwnedMutexGuard, + OwnedMutexLockFuture, }; #[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))]