Skip to content

Commit a7ddc7b

Browse files
committed
init
1 parent 5f3b84a commit a7ddc7b

File tree

2 files changed

+35
-0
lines changed

2 files changed

+35
-0
lines changed

Diff for: library/std/src/sync/poison/rwlock.rs

+15
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::sync::PoisonError;
2+
13
use crate::cell::UnsafeCell;
24
use crate::fmt;
35
use crate::marker::PhantomData;
@@ -918,6 +920,19 @@ impl<'a, T: ?Sized> RwLockReadGuard<'a, T> {
918920
None => Err(orig),
919921
}
920922
}
923+
924+
pub fn try_upgrade<T>(orig: Self) -> Result<RwLockWriteGuard<'a, T>, RwLockReadGuard<'a, T>> {
925+
read_lock = orig.inner_lock;
926+
927+
// don't call the destructor
928+
forget(read_lock);
929+
930+
// SAFETY: We have ownership of the read guard, so it must be in read mode already
931+
match unsafe { read_lock.try_upgrade() } {
932+
true => RwLockWriteGuard::new(read_lock).unwrap_or_else(PoisonError::into_inner),
933+
false => RwLockReadGuard::new(read_lock).unwrap_or_else(PoisonError::into_inner),
934+
}
935+
}
921936
}
922937

923938
impl<'a, T: ?Sized> MappedRwLockReadGuard<'a, T> {

Diff for: library/std/src/sys/sync/rwlock/futex.rs

+20
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::sync::atomic::Ordering::{Acquire, Relaxed};
2+
13
use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release};
24
use crate::sys::futex::{Futex, Primitive, futex_wait, futex_wake, futex_wake_all};
35

@@ -33,6 +35,11 @@ fn is_write_locked(state: Primitive) -> bool {
3335
state & MASK == WRITE_LOCKED
3436
}
3537

38+
#[inline]
39+
fn is_read_locked(state: Primitive) -> bool {
40+
state & MASK == READ_LOCKED
41+
}
42+
3643
#[inline]
3744
fn has_readers_waiting(state: Primitive) -> bool {
3845
state & READERS_WAITING != 0
@@ -205,6 +212,19 @@ impl RwLock {
205212
}
206213
}
207214

215+
/// # Safety
216+
///
217+
/// The 'RwLock' must be read-locked in order to call this. Calling this function in a loop
218+
/// in at least 2 threads will deadlock.
219+
#[inline]
220+
pub unsafe fn try_upgrade(&self) -> bool {
221+
debug_assert!(
222+
is_read_locked(self.state),
223+
"RwLock must be read locked to call `try_upgrade`"
224+
);
225+
self.state.compare_exchange(READ_LOCKED, WRITE_LOCKED, Acquire, Relaxed).is_ok()
226+
}
227+
208228
#[cold]
209229
fn write_contended(&self) {
210230
let mut state = self.spin_write();

0 commit comments

Comments
 (0)