Rollup merge of #147328 - EFanZh:lock-with, r=joboet

Implement non-poisoning `Mutex::with_mut`, `RwLock::with` and `RwLock::with_mut`

ACP: https://github.com/rust-lang/libs-team/issues/497.
This commit is contained in:
Stuart Cook 2025-10-05 15:35:04 +11:00 committed by GitHub
commit 56c96aebfc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 132 additions and 0 deletions

View File

@ -376,6 +376,40 @@ impl<T: ?Sized> Mutex<T> {
pub const fn data_ptr(&self) -> *mut T {
self.data.get()
}
/// Acquires the mutex and provides mutable access to the underlying data by passing
/// a mutable reference to the given closure.
///
/// This method acquires the lock, calls the provided closure with a mutable reference
/// to the data, and returns the result of the closure. The lock is released after
/// the closure completes, even if it panics.
///
/// # Examples
///
/// ```
/// #![feature(lock_value_accessors, nonpoison_mutex)]
///
/// use std::sync::nonpoison::Mutex;
///
/// let mutex = Mutex::new(2);
///
/// let result = mutex.with_mut(|data| {
/// *data += 3;
///
/// *data + 5
/// });
///
/// assert_eq!(*mutex.lock(), 5);
/// assert_eq!(result, 10);
/// ```
#[unstable(feature = "lock_value_accessors", issue = "133407")]
// #[unstable(feature = "nonpoison_mutex", issue = "134645")]
pub fn with_mut<F, R>(&self, f: F) -> R
where
F: FnOnce(&mut T) -> R,
{
f(&mut self.lock())
}
}
#[unstable(feature = "nonpoison_mutex", issue = "134645")]

View File

@ -498,6 +498,68 @@ impl<T: ?Sized> RwLock<T> {
pub const fn data_ptr(&self) -> *mut T {
self.data.get()
}
/// Locks this `RwLock` with shared read access to the underlying data by passing
/// a reference to the given closure.
///
/// This method acquires the lock, calls the provided closure with a reference
/// to the data, and returns the result of the closure. The lock is released after
/// the closure completes, even if it panics.
///
/// # Examples
///
/// ```
/// #![feature(lock_value_accessors, nonpoison_rwlock)]
///
/// use std::sync::nonpoison::RwLock;
///
/// let rwlock = RwLock::new(2);
/// let result = rwlock.with(|data| *data + 3);
///
/// assert_eq!(result, 5);
/// ```
#[unstable(feature = "lock_value_accessors", issue = "133407")]
// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
pub fn with<F, R>(&self, f: F) -> R
where
F: FnOnce(&T) -> R,
{
f(&self.read())
}
/// Locks this `RwLock` with exclusive write access to the underlying data by passing
/// a mutable reference to the given closure.
///
/// This method acquires the lock, calls the provided closure with a mutable reference
/// to the data, and returns the result of the closure. The lock is released after
/// the closure completes, even if it panics.
///
/// # Examples
///
/// ```
/// #![feature(lock_value_accessors, nonpoison_rwlock)]
///
/// use std::sync::nonpoison::RwLock;
///
/// let rwlock = RwLock::new(2);
///
/// let result = rwlock.with_mut(|data| {
/// *data += 3;
///
/// *data + 5
/// });
///
/// assert_eq!(*rwlock.read(), 5);
/// assert_eq!(result, 10);
/// ```
#[unstable(feature = "lock_value_accessors", issue = "133407")]
// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
pub fn with_mut<F, R>(&self, f: F) -> R
where
F: FnOnce(&mut T) -> R,
{
f(&mut self.write())
}
}
#[unstable(feature = "nonpoison_rwlock", issue = "134645")]

View File

@ -549,3 +549,17 @@ fn panic_while_mapping_unlocked_poison() {
drop(lock);
}
#[test]
fn test_mutex_with_mut() {
let mutex = std::sync::nonpoison::Mutex::new(2);
let result = mutex.with_mut(|value| {
*value += 3;
*value + 5
});
assert_eq!(*mutex.lock(), 5);
assert_eq!(result, 10);
}

View File

@ -861,3 +861,25 @@ fn panic_while_mapping_write_unlocked_poison() {
drop(lock);
}
#[test]
fn test_rwlock_with() {
let rwlock = std::sync::nonpoison::RwLock::new(2);
let result = rwlock.with(|value| *value + 3);
assert_eq!(result, 5);
}
#[test]
fn test_rwlock_with_mut() {
let rwlock = std::sync::nonpoison::RwLock::new(2);
let result = rwlock.with_mut(|value| {
*value += 3;
*value + 5
});
assert_eq!(*rwlock.read(), 5);
assert_eq!(result, 10);
}