Skip to content

Commit 9b2112a

Browse files
committed
Use Pin to pin RwLock.
1 parent 1935645 commit 9b2112a

File tree

4 files changed

+50
-67
lines changed

4 files changed

+50
-67
lines changed

library/std/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,7 @@
289289
#![feature(panic_info_message)]
290290
#![feature(panic_internals)]
291291
#![feature(panic_unwind)]
292+
#![feature(pin_static_ref)]
292293
#![feature(prelude_import)]
293294
#![feature(ptr_internals)]
294295
#![feature(raw)]

library/std/src/panicking.rs

+7-6
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use crate::any::Any;
1515
use crate::fmt;
1616
use crate::intrinsics;
1717
use crate::mem::{self, ManuallyDrop};
18+
use crate::pin::Pin;
1819
use crate::process;
1920
use crate::sync::atomic::{AtomicBool, Ordering};
2021
use crate::sys::stdio::panic_output;
@@ -116,11 +117,11 @@ pub fn set_hook(hook: Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send>) {
116117
panic!("cannot modify the panic hook from a panicking thread");
117118
}
118119

120+
Pin::static_ref(&HOOK_LOCK).write();
119121
unsafe {
120-
HOOK_LOCK.write();
121122
let old_hook = HOOK;
122123
HOOK = Hook::Custom(Box::into_raw(hook));
123-
HOOK_LOCK.write_unlock();
124+
Pin::static_ref(&HOOK_LOCK).write_unlock();
124125

125126
if let Hook::Custom(ptr) = old_hook {
126127
#[allow(unused_must_use)]
@@ -164,11 +165,11 @@ pub fn take_hook() -> Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send> {
164165
panic!("cannot modify the panic hook from a panicking thread");
165166
}
166167

168+
Pin::static_ref(&HOOK_LOCK).write();
167169
unsafe {
168-
HOOK_LOCK.write();
169170
let hook = HOOK;
170171
HOOK = Hook::Default;
171-
HOOK_LOCK.write_unlock();
172+
Pin::static_ref(&HOOK_LOCK).write_unlock();
172173

173174
match hook {
174175
Hook::Default => Box::new(default_hook),
@@ -563,7 +564,7 @@ fn rust_panic_with_hook(
563564

564565
unsafe {
565566
let mut info = PanicInfo::internal_constructor(message, location);
566-
HOOK_LOCK.read();
567+
Pin::static_ref(&HOOK_LOCK).read();
567568
match HOOK {
568569
// Some platforms (like wasm) know that printing to stderr won't ever actually
569570
// print anything, and if that's the case we can skip the default
@@ -581,7 +582,7 @@ fn rust_panic_with_hook(
581582
(*ptr)(&info);
582583
}
583584
};
584-
HOOK_LOCK.read_unlock();
585+
Pin::static_ref(&HOOK_LOCK).read_unlock();
585586
}
586587

587588
if panics > 1 {

library/std/src/sync/rwlock.rs

+25-33
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use crate::cell::UnsafeCell;
55
use crate::fmt;
66
use crate::mem;
77
use crate::ops::{Deref, DerefMut};
8+
use crate::pin::Pin;
89
use crate::ptr;
910
use crate::sys_common::poison::{self, LockResult, TryLockError, TryLockResult};
1011
use crate::sys_common::rwlock as sys;
@@ -64,7 +65,7 @@ use crate::sys_common::rwlock as sys;
6465
/// [`Mutex`]: super::Mutex
6566
#[stable(feature = "rust1", since = "1.0.0")]
6667
pub struct RwLock<T: ?Sized> {
67-
inner: Box<sys::RWLock>,
68+
inner: Pin<Box<sys::RWLock>>,
6869
poison: poison::Flag,
6970
data: UnsafeCell<T>,
7071
}
@@ -128,7 +129,7 @@ impl<T> RwLock<T> {
128129
#[stable(feature = "rust1", since = "1.0.0")]
129130
pub fn new(t: T) -> RwLock<T> {
130131
RwLock {
131-
inner: box sys::RWLock::new(),
132+
inner: Box::pin(sys::RWLock::new()),
132133
poison: poison::Flag::new(),
133134
data: UnsafeCell::new(t),
134135
}
@@ -178,10 +179,9 @@ impl<T: ?Sized> RwLock<T> {
178179
#[inline]
179180
#[stable(feature = "rust1", since = "1.0.0")]
180181
pub fn read(&self) -> LockResult<RwLockReadGuard<'_, T>> {
181-
unsafe {
182-
self.inner.read();
183-
RwLockReadGuard::new(self)
184-
}
182+
self.inner.as_ref().read();
183+
// SAFETY: We've gotten a read-lock on the rwlock.
184+
unsafe { RwLockReadGuard::new(self) }
185185
}
186186

187187
/// Attempts to acquire this rwlock with shared read access.
@@ -217,12 +217,11 @@ impl<T: ?Sized> RwLock<T> {
217217
#[inline]
218218
#[stable(feature = "rust1", since = "1.0.0")]
219219
pub fn try_read(&self) -> TryLockResult<RwLockReadGuard<'_, T>> {
220-
unsafe {
221-
if self.inner.try_read() {
222-
Ok(RwLockReadGuard::new(self)?)
223-
} else {
224-
Err(TryLockError::WouldBlock)
225-
}
220+
if self.inner.as_ref().try_read() {
221+
// SAFETY: We've gotten a read-lock on the rwlock.
222+
unsafe { Ok(RwLockReadGuard::new(self)?) }
223+
} else {
224+
Err(TryLockError::WouldBlock)
226225
}
227226
}
228227

@@ -260,10 +259,9 @@ impl<T: ?Sized> RwLock<T> {
260259
#[inline]
261260
#[stable(feature = "rust1", since = "1.0.0")]
262261
pub fn write(&self) -> LockResult<RwLockWriteGuard<'_, T>> {
263-
unsafe {
264-
self.inner.write();
265-
RwLockWriteGuard::new(self)
266-
}
262+
self.inner.as_ref().write();
263+
// SAFETY: We've gotten a write-lock on the rwlock.
264+
unsafe { RwLockWriteGuard::new(self) }
267265
}
268266

269267
/// Attempts to lock this rwlock with exclusive write access.
@@ -299,12 +297,11 @@ impl<T: ?Sized> RwLock<T> {
299297
#[inline]
300298
#[stable(feature = "rust1", since = "1.0.0")]
301299
pub fn try_write(&self) -> TryLockResult<RwLockWriteGuard<'_, T>> {
302-
unsafe {
303-
if self.inner.try_write() {
304-
Ok(RwLockWriteGuard::new(self)?)
305-
} else {
306-
Err(TryLockError::WouldBlock)
307-
}
300+
if self.inner.as_ref().try_write() {
301+
// SAFETY: We've gotten a write-lock on the rwlock.
302+
unsafe { Ok(RwLockWriteGuard::new(self)?) }
303+
} else {
304+
Err(TryLockError::WouldBlock)
308305
}
309306
}
310307

@@ -374,7 +371,6 @@ impl<T: ?Sized> RwLock<T> {
374371
(ptr::read(inner), ptr::read(poison), ptr::read(data))
375372
};
376373
mem::forget(self);
377-
inner.destroy(); // Keep in sync with the `Drop` impl.
378374
drop(inner);
379375

380376
poison::map_result(poison.borrow(), |_| data.into_inner())
@@ -409,14 +405,6 @@ impl<T: ?Sized> RwLock<T> {
409405
}
410406
}
411407

412-
#[stable(feature = "rust1", since = "1.0.0")]
413-
unsafe impl<#[may_dangle] T: ?Sized> Drop for RwLock<T> {
414-
fn drop(&mut self) {
415-
// IMPORTANT: This code needs to be kept in sync with `RwLock::into_inner`.
416-
unsafe { self.inner.destroy() }
417-
}
418-
}
419-
420408
#[stable(feature = "rust1", since = "1.0.0")]
421409
impl<T: ?Sized + fmt::Debug> fmt::Debug for RwLock<T> {
422410
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -524,8 +512,10 @@ impl<T: ?Sized> DerefMut for RwLockWriteGuard<'_, T> {
524512
#[stable(feature = "rust1", since = "1.0.0")]
525513
impl<T: ?Sized> Drop for RwLockReadGuard<'_, T> {
526514
fn drop(&mut self) {
515+
// SAFETY: The fact that we have a RwLockReadGuard proves this thread
516+
// has this rwlock read-locked.
527517
unsafe {
528-
self.lock.inner.read_unlock();
518+
self.lock.inner.as_ref().read_unlock();
529519
}
530520
}
531521
}
@@ -534,8 +524,10 @@ impl<T: ?Sized> Drop for RwLockReadGuard<'_, T> {
534524
impl<T: ?Sized> Drop for RwLockWriteGuard<'_, T> {
535525
fn drop(&mut self) {
536526
self.lock.poison.done(&self.poison);
527+
// SAFETY: The fact that we have a RwLockWriteGuard proves this thread
528+
// has this rwlock write-locked.
537529
unsafe {
538-
self.lock.inner.write_unlock();
530+
self.lock.inner.as_ref().write_unlock();
539531
}
540532
}
541533
}

library/std/src/sys_common/rwlock.rs

+17-28
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::pin::Pin;
12
use crate::sys::rwlock as imp;
23

34
/// An OS-based reader-writer lock.
@@ -18,53 +19,41 @@ impl RWLock {
1819

1920
/// Acquires shared access to the underlying lock, blocking the current
2021
/// thread to do so.
21-
///
22-
/// Behavior is undefined if the rwlock has been moved between this and any
23-
/// previous method call.
2422
#[inline]
25-
pub unsafe fn read(&self) {
26-
self.0.read()
23+
pub fn read(self: Pin<&Self>) {
24+
unsafe { self.0.read() }
2725
}
2826

2927
/// Attempts to acquire shared access to this lock, returning whether it
3028
/// succeeded or not.
3129
///
3230
/// This function does not block the current thread.
33-
///
34-
/// Behavior is undefined if the rwlock has been moved between this and any
35-
/// previous method call.
3631
#[inline]
37-
pub unsafe fn try_read(&self) -> bool {
38-
self.0.try_read()
32+
pub fn try_read(self: Pin<&Self>) -> bool {
33+
unsafe { self.0.try_read() }
3934
}
4035

4136
/// Acquires write access to the underlying lock, blocking the current thread
4237
/// to do so.
43-
///
44-
/// Behavior is undefined if the rwlock has been moved between this and any
45-
/// previous method call.
4638
#[inline]
47-
pub unsafe fn write(&self) {
48-
self.0.write()
39+
pub fn write(self: Pin<&Self>) {
40+
unsafe { self.0.write() }
4941
}
5042

5143
/// Attempts to acquire exclusive access to this lock, returning whether it
5244
/// succeeded or not.
5345
///
5446
/// This function does not block the current thread.
55-
///
56-
/// Behavior is undefined if the rwlock has been moved between this and any
57-
/// previous method call.
5847
#[inline]
59-
pub unsafe fn try_write(&self) -> bool {
60-
self.0.try_write()
48+
pub fn try_write(self: Pin<&Self>) -> bool {
49+
unsafe { self.0.try_write() }
6150
}
6251

6352
/// Unlocks previously acquired shared access to this lock.
6453
///
6554
/// Behavior is undefined if the current thread does not have shared access.
6655
#[inline]
67-
pub unsafe fn read_unlock(&self) {
56+
pub unsafe fn read_unlock(self: Pin<&Self>) {
6857
self.0.read_unlock()
6958
}
7059

@@ -73,16 +62,16 @@ impl RWLock {
7362
/// Behavior is undefined if the current thread does not currently have
7463
/// exclusive access.
7564
#[inline]
76-
pub unsafe fn write_unlock(&self) {
65+
pub unsafe fn write_unlock(self: Pin<&Self>) {
7766
self.0.write_unlock()
7867
}
68+
}
7969

80-
/// Destroys OS-related resources with this RWLock.
81-
///
82-
/// Behavior is undefined if there are any currently active users of this
83-
/// lock.
70+
impl Drop for RWLock {
8471
#[inline]
85-
pub unsafe fn destroy(&self) {
86-
self.0.destroy()
72+
fn drop(&mut self) {
73+
// SAFETY: The rwlock wasn't moved since using any of its
74+
// functions, because they all require a Pin.
75+
unsafe { self.0.destroy() }
8776
}
8877
}

0 commit comments

Comments
 (0)