Skip to content

Commit 7cb2363

Browse files
authored
Unrolled build for #147328
Rollup merge of #147328 - EFanZh:lock-with, r=joboet Implement non-poisoning `Mutex::with_mut`, `RwLock::with` and `RwLock::with_mut` ACP: rust-lang/libs-team#497.
2 parents 227ac7c + ba42380 commit 7cb2363

File tree

4 files changed

+132
-0
lines changed

4 files changed

+132
-0
lines changed

library/std/src/sync/nonpoison/mutex.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,40 @@ impl<T: ?Sized> Mutex<T> {
376376
pub const fn data_ptr(&self) -> *mut T {
377377
self.data.get()
378378
}
379+
380+
/// Acquires the mutex and provides mutable access to the underlying data by passing
381+
/// a mutable reference to the given closure.
382+
///
383+
/// This method acquires the lock, calls the provided closure with a mutable reference
384+
/// to the data, and returns the result of the closure. The lock is released after
385+
/// the closure completes, even if it panics.
386+
///
387+
/// # Examples
388+
///
389+
/// ```
390+
/// #![feature(lock_value_accessors, nonpoison_mutex)]
391+
///
392+
/// use std::sync::nonpoison::Mutex;
393+
///
394+
/// let mutex = Mutex::new(2);
395+
///
396+
/// let result = mutex.with_mut(|data| {
397+
/// *data += 3;
398+
///
399+
/// *data + 5
400+
/// });
401+
///
402+
/// assert_eq!(*mutex.lock(), 5);
403+
/// assert_eq!(result, 10);
404+
/// ```
405+
#[unstable(feature = "lock_value_accessors", issue = "133407")]
406+
// #[unstable(feature = "nonpoison_mutex", issue = "134645")]
407+
pub fn with_mut<F, R>(&self, f: F) -> R
408+
where
409+
F: FnOnce(&mut T) -> R,
410+
{
411+
f(&mut self.lock())
412+
}
379413
}
380414

381415
#[unstable(feature = "nonpoison_mutex", issue = "134645")]

library/std/src/sync/nonpoison/rwlock.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,68 @@ impl<T: ?Sized> RwLock<T> {
498498
pub const fn data_ptr(&self) -> *mut T {
499499
self.data.get()
500500
}
501+
502+
/// Locks this `RwLock` with shared read access to the underlying data by passing
503+
/// a reference to the given closure.
504+
///
505+
/// This method acquires the lock, calls the provided closure with a reference
506+
/// to the data, and returns the result of the closure. The lock is released after
507+
/// the closure completes, even if it panics.
508+
///
509+
/// # Examples
510+
///
511+
/// ```
512+
/// #![feature(lock_value_accessors, nonpoison_rwlock)]
513+
///
514+
/// use std::sync::nonpoison::RwLock;
515+
///
516+
/// let rwlock = RwLock::new(2);
517+
/// let result = rwlock.with(|data| *data + 3);
518+
///
519+
/// assert_eq!(result, 5);
520+
/// ```
521+
#[unstable(feature = "lock_value_accessors", issue = "133407")]
522+
// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
523+
pub fn with<F, R>(&self, f: F) -> R
524+
where
525+
F: FnOnce(&T) -> R,
526+
{
527+
f(&self.read())
528+
}
529+
530+
/// Locks this `RwLock` with exclusive write access to the underlying data by passing
531+
/// a mutable reference to the given closure.
532+
///
533+
/// This method acquires the lock, calls the provided closure with a mutable reference
534+
/// to the data, and returns the result of the closure. The lock is released after
535+
/// the closure completes, even if it panics.
536+
///
537+
/// # Examples
538+
///
539+
/// ```
540+
/// #![feature(lock_value_accessors, nonpoison_rwlock)]
541+
///
542+
/// use std::sync::nonpoison::RwLock;
543+
///
544+
/// let rwlock = RwLock::new(2);
545+
///
546+
/// let result = rwlock.with_mut(|data| {
547+
/// *data += 3;
548+
///
549+
/// *data + 5
550+
/// });
551+
///
552+
/// assert_eq!(*rwlock.read(), 5);
553+
/// assert_eq!(result, 10);
554+
/// ```
555+
#[unstable(feature = "lock_value_accessors", issue = "133407")]
556+
// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
557+
pub fn with_mut<F, R>(&self, f: F) -> R
558+
where
559+
F: FnOnce(&mut T) -> R,
560+
{
561+
f(&mut self.write())
562+
}
501563
}
502564

503565
#[unstable(feature = "nonpoison_rwlock", issue = "134645")]

library/std/tests/sync/mutex.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,3 +549,17 @@ fn panic_while_mapping_unlocked_poison() {
549549

550550
drop(lock);
551551
}
552+
553+
#[test]
554+
fn test_mutex_with_mut() {
555+
let mutex = std::sync::nonpoison::Mutex::new(2);
556+
557+
let result = mutex.with_mut(|value| {
558+
*value += 3;
559+
560+
*value + 5
561+
});
562+
563+
assert_eq!(*mutex.lock(), 5);
564+
assert_eq!(result, 10);
565+
}

library/std/tests/sync/rwlock.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -861,3 +861,25 @@ fn panic_while_mapping_write_unlocked_poison() {
861861

862862
drop(lock);
863863
}
864+
865+
#[test]
866+
fn test_rwlock_with() {
867+
let rwlock = std::sync::nonpoison::RwLock::new(2);
868+
let result = rwlock.with(|value| *value + 3);
869+
870+
assert_eq!(result, 5);
871+
}
872+
873+
#[test]
874+
fn test_rwlock_with_mut() {
875+
let rwlock = std::sync::nonpoison::RwLock::new(2);
876+
877+
let result = rwlock.with_mut(|value| {
878+
*value += 3;
879+
880+
*value + 5
881+
});
882+
883+
assert_eq!(*rwlock.read(), 5);
884+
assert_eq!(result, 10);
885+
}

0 commit comments

Comments
 (0)