Skip to content

Commit f750d12

Browse files
committed
Add with_read/with_write to RwLock
1 parent 8feec21 commit f750d12

File tree

1 file changed

+74
-0
lines changed

1 file changed

+74
-0
lines changed

src/libstd/sync/rwlock.rs

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,60 @@ impl<T: ?Sized> RwLock<T> {
409409
let data = unsafe { &mut *self.data.get() };
410410
poison::map_result(self.poison.borrow(), |_| data)
411411
}
412+
413+
/// Call function while holding write lock
414+
///
415+
/// This attempts to take the write lock, and if successful passes a mutable
416+
/// reference to the value to the callback.
417+
///
418+
/// # Panics
419+
///
420+
/// This function will panic if the RwLock is poisoned. An RwLock
421+
/// is poisoned whenever a writer panics while holding an exclusive lock.
422+
///
423+
/// # Example
424+
///
425+
/// ```
426+
/// # #![feature(mutex_with)]
427+
/// use std::sync::RwLock;
428+
///
429+
/// let rw = RwLock::new(String::new());
430+
///
431+
/// let prev = rw.with_write(|mut s| {
432+
/// let prev = s.clone();
433+
/// *s += "foo";
434+
/// prev
435+
/// });
436+
/// ```
437+
#[unstable(feature = "mutex_with", issue = "61974")]
438+
pub fn with_write<U, F: FnOnce(&mut T) -> U>(&self, func: F) -> U {
439+
self.write().map(|mut v| func(&mut *v)).expect("RwLock poisoned")
440+
}
441+
442+
/// Call function while holding read lock
443+
///
444+
/// This attempts to take the read lock, and if successful passes a
445+
/// reference to the value to the callback.
446+
///
447+
/// # Panics
448+
///
449+
/// This function will panic if the RwLock is poisoned. An RwLock
450+
/// is poisoned whenever a writer panics while holding an exclusive lock.
451+
///
452+
/// # Example
453+
///
454+
/// ```
455+
/// # #![feature(mutex_with)]
456+
/// use std::sync::RwLock;
457+
///
458+
/// let rw = RwLock::new("hello world".to_string());
459+
///
460+
/// let val = rw.with_read(|s| s.clone());
461+
/// ```
462+
#[unstable(feature = "mutex_with", issue = "61974")]
463+
pub fn with_read<U, F: FnOnce(&T) -> U>(&self, func: F) -> U {
464+
self.read().map(|v| func(&*v)).expect("RwLock poisoned")
465+
}
412466
}
413467

414468
#[stable(feature = "rust1", since = "1.0.0")]
@@ -797,4 +851,24 @@ mod tests {
797851
Ok(x) => panic!("get_mut of poisoned RwLock is Ok: {:?}", x),
798852
}
799853
}
854+
855+
#[test]
856+
fn test_with_read() {
857+
let m = RwLock::new(10);
858+
859+
let v = m.with_read(|v| *v);
860+
861+
assert_eq!(v, 10);
862+
}
863+
864+
#[test]
865+
fn test_with_write() {
866+
let m = RwLock::new(10);
867+
868+
let old = m.with_write(|v| {let old = *v; *v += 1; old});
869+
let now = m.with_read(|v| *v);
870+
871+
assert_eq!(old, 10);
872+
assert_eq!(now, 11);
873+
}
800874
}

0 commit comments

Comments
 (0)