Skip to content

Commit e130930

Browse files
committed
implement feature lock_value_accessors
1 parent 1428944 commit e130930

File tree

2 files changed

+118
-44
lines changed

2 files changed

+118
-44
lines changed

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

Lines changed: 72 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::cell::UnsafeCell;
22
use crate::fmt;
33
use crate::marker::PhantomData;
4-
use crate::mem::ManuallyDrop;
4+
use crate::mem::{self, ManuallyDrop};
55
use crate::ops::{Deref, DerefMut};
66
use crate::ptr::NonNull;
77
use crate::sync::nonpoison::{TryLockResult, WouldBlock};
@@ -259,6 +259,7 @@ impl<T> Mutex<T> {
259259
///
260260
/// ```
261261
/// #![feature(nonpoison_mutex)]
262+
///
262263
/// use std::sync::nonpoison::Mutex;
263264
///
264265
/// let mutex = Mutex::new(0);
@@ -269,7 +270,72 @@ impl<T> Mutex<T> {
269270
Mutex { inner: sys::Mutex::new(), data: UnsafeCell::new(t) }
270271
}
271272

272-
// FIXME: Add `lock_value_accessors` feature methods.
273+
/// Returns the contained value by cloning it.
274+
///
275+
/// # Examples
276+
///
277+
/// ```
278+
/// #![feature(nonpoison_mutex)]
279+
/// #![feature(lock_value_accessors)]
280+
///
281+
/// use std::sync::nonpoison::Mutex;
282+
///
283+
/// let mut mutex = Mutex::new(7);
284+
///
285+
/// assert_eq!(mutex.get_cloned(), 7);
286+
/// ```
287+
#[unstable(feature = "lock_value_accessors", issue = "133407")]
288+
pub fn get_cloned(&self) -> T
289+
where
290+
T: Clone,
291+
{
292+
self.lock().clone()
293+
}
294+
295+
/// Sets the contained value.
296+
///
297+
/// # Examples
298+
///
299+
/// ```
300+
/// #![feature(nonpoison_mutex)]
301+
/// #![feature(lock_value_accessors)]
302+
///
303+
/// use std::sync::nonpoison::Mutex;
304+
///
305+
/// let mut mutex = Mutex::new(7);
306+
///
307+
/// assert_eq!(mutex.get_cloned(), 7);
308+
/// mutex.set(11);
309+
/// assert_eq!(mutex.get_cloned(), 11);
310+
/// ```
311+
#[unstable(feature = "lock_value_accessors", issue = "133407")]
312+
pub fn set(&self, value: T) {
313+
let old = self.replace(value);
314+
if mem::needs_drop::<T>() {
315+
drop(old)
316+
}
317+
}
318+
319+
/// Replaces the contained value with `value`, and returns the old contained value.
320+
///
321+
/// # Examples
322+
///
323+
/// ```
324+
/// #![feature(nonpoison_mutex)]
325+
/// #![feature(lock_value_accessors)]
326+
///
327+
/// use std::sync::nonpoison::Mutex;
328+
///
329+
/// let mut mutex = Mutex::new(7);
330+
///
331+
/// assert_eq!(mutex.replace(11), 7);
332+
/// assert_eq!(mutex.get_cloned(), 11);
333+
/// ```
334+
#[unstable(feature = "lock_value_accessors", issue = "133407")]
335+
pub fn replace(&self, value: T) -> T {
336+
let mut guard = self.lock();
337+
mem::replace(&mut *guard, value)
338+
}
273339
}
274340

275341
impl<T: ?Sized> Mutex<T> {
@@ -293,6 +359,7 @@ impl<T: ?Sized> Mutex<T> {
293359
///
294360
/// ```
295361
/// #![feature(nonpoison_mutex)]
362+
///
296363
/// use std::sync::{Arc, nonpoison::Mutex};
297364
/// use std::thread;
298365
///
@@ -329,6 +396,7 @@ impl<T: ?Sized> Mutex<T> {
329396
///
330397
/// ```
331398
/// #![feature(nonpoison_mutex)]
399+
///
332400
/// use std::sync::{Arc, nonpoison::Mutex};
333401
/// use std::thread;
334402
///
@@ -356,6 +424,7 @@ impl<T: ?Sized> Mutex<T> {
356424
///
357425
/// ```
358426
/// #![feature(nonpoison_mutex)]
427+
///
359428
/// use std::sync::nonpoison::Mutex;
360429
///
361430
/// let mutex = Mutex::new(0);
@@ -378,6 +447,7 @@ impl<T: ?Sized> Mutex<T> {
378447
///
379448
/// ```
380449
/// #![feature(nonpoison_mutex)]
450+
///
381451
/// use std::sync::nonpoison::Mutex;
382452
///
383453
/// let mut mutex = Mutex::new(0);

library/std/tests/sync/mutex.rs

Lines changed: 46 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ use std::{hint, mem, thread};
1010
//
1111
// To write a test that uses both `poison::Mutex` and `nonpoison::Mutex`, simply call the macro
1212
// `maybe_unwrap!(...)` on the result of `mutex.lock()`. For the `poison::Mutex`, it will unwrap the
13-
// `LockResult`, but for the `nonpoison::Mutex` it will do nothing.
13+
// `Result` (usually `LockResult`, but it could be other kinds of results), but for the
14+
// `nonpoison::Mutex` it will do nothing.
1415
//
1516
// The `poison` test will have the same name, but with a suffix of `_unwrap_poisoned`.
1617
//
@@ -38,11 +39,11 @@ macro_rules! nonpoison_and_poison_unwrap_test {
3839
#[test]
3940
fn ${concat($name, _unwrap_poisoned)}() {
4041
#[allow(unused_imports)]
41-
use ::std::sync::{Mutex, MappedMutexGuard, MutexGuard, LockResult};
42+
use ::std::sync::{Mutex, MappedMutexGuard, MutexGuard};
4243

4344
#[allow(unused_macros)]
4445
macro_rules! maybe_unwrap {
45-
($e:expr) => { LockResult::unwrap($e) };
46+
($e:expr) => { Result::unwrap($e) };
4647
}
4748

4849
$($test_body)*
@@ -151,17 +152,6 @@ nonpoison_and_poison_unwrap_test!(
151152
}
152153
);
153154

154-
// TODO(connor): make this a double test after implementing `lock_value_accessors` on `nonpoison`.
155-
#[test]
156-
fn test_get_cloned() {
157-
#[derive(Clone, Eq, PartialEq, Debug)]
158-
struct Cloneable(i32);
159-
160-
let m = Mutex::new(Cloneable(10));
161-
162-
assert_eq!(m.get_cloned().unwrap(), Cloneable(10));
163-
}
164-
165155
nonpoison_and_poison_unwrap_test!(
166156
name: test_get_mut,
167157
test_body: {
@@ -171,41 +161,55 @@ nonpoison_and_poison_unwrap_test!(
171161
}
172162
);
173163

174-
// TODO(connor): make this a double test after implementing `lock_value_accessors` on `nonpoison`.
175-
#[test]
176-
fn test_set() {
177-
fn inner<T>(mut init: impl FnMut() -> T, mut value: impl FnMut() -> T)
178-
where
179-
T: Debug + Eq,
180-
{
181-
let m = Mutex::new(init());
164+
nonpoison_and_poison_unwrap_test!(
165+
name: test_get_cloned,
166+
test_body: {
167+
#[derive(Clone, Eq, PartialEq, Debug)]
168+
struct Cloneable(i32);
169+
170+
let m = Mutex::new(Cloneable(10));
182171

183-
assert_eq!(*m.lock().unwrap(), init());
184-
m.set(value()).unwrap();
185-
assert_eq!(*m.lock().unwrap(), value());
172+
assert_eq!(maybe_unwrap!(m.get_cloned()), Cloneable(10));
186173
}
174+
);
187175

188-
inner(|| NonCopy(10), || NonCopy(20));
189-
inner(|| NonCopyNeedsDrop(10), || NonCopyNeedsDrop(20));
190-
}
176+
nonpoison_and_poison_unwrap_test!(
177+
name: test_set,
178+
test_body: {
179+
fn inner<T>(mut init: impl FnMut() -> T, mut value: impl FnMut() -> T)
180+
where
181+
T: Debug + Eq,
182+
{
183+
let m = Mutex::new(init());
191184

192-
// TODO(connor): make this a double test after implementing `lock_value_accessors` on `nonpoison`.
193-
#[test]
194-
fn test_replace() {
195-
fn inner<T>(mut init: impl FnMut() -> T, mut value: impl FnMut() -> T)
196-
where
197-
T: Debug + Eq,
198-
{
199-
let m = Mutex::new(init());
185+
assert_eq!(*maybe_unwrap!(m.lock()), init());
186+
maybe_unwrap!(m.set(value()));
187+
assert_eq!(*maybe_unwrap!(m.lock()), value());
188+
}
200189

201-
assert_eq!(*m.lock().unwrap(), init());
202-
assert_eq!(m.replace(value()).unwrap(), init());
203-
assert_eq!(*m.lock().unwrap(), value());
190+
inner(|| NonCopy(10), || NonCopy(20));
191+
inner(|| NonCopyNeedsDrop(10), || NonCopyNeedsDrop(20));
204192
}
193+
);
205194

206-
inner(|| NonCopy(10), || NonCopy(20));
207-
inner(|| NonCopyNeedsDrop(10), || NonCopyNeedsDrop(20));
208-
}
195+
nonpoison_and_poison_unwrap_test!(
196+
name: test_replace,
197+
test_body: {
198+
fn inner<T>(mut init: impl FnMut() -> T, mut value: impl FnMut() -> T)
199+
where
200+
T: Debug + Eq,
201+
{
202+
let m = Mutex::new(init());
203+
204+
assert_eq!(*maybe_unwrap!(m.lock()), init());
205+
assert_eq!(maybe_unwrap!(m.replace(value())), init());
206+
assert_eq!(*maybe_unwrap!(m.lock()), value());
207+
}
208+
209+
inner(|| NonCopy(10), || NonCopy(20));
210+
inner(|| NonCopyNeedsDrop(10), || NonCopyNeedsDrop(20));
211+
}
212+
);
209213

210214
#[test]
211215
fn test_mutex_arc_condvar() {

0 commit comments

Comments
 (0)