use core::cell::UnsafeCell;
use core::fmt;
use core::marker::PhantomData;
use core::mem;
use core::ops::{Deref, DerefMut};
use crate::guard::{ExclusiveGuardData, SharedGuardData, abort_on_panic};
#[cfg(feature = "arc_lock")]
use alloc::sync::Arc;
use core::mem::ManuallyDrop;
use core::ptr;
#[cfg(feature = "owning_ref")]
use owning_ref::StableAddress;
#[cfg(feature = "serde")]
use serde::{Deserialize, Deserializer, Serialize, Serializer};
pub unsafe trait RawRwLock {
#[allow(clippy::declare_interior_mutable_const)]
const INIT: Self;
type SharedGuard;
type ExclusiveGuard;
fn lock_shared(&self) -> Self::SharedGuard;
fn try_lock_shared(&self) -> Option<Self::SharedGuard>;
unsafe fn unlock_shared(&self, guard: Self::SharedGuard);
fn lock_exclusive(&self) -> Self::ExclusiveGuard;
fn try_lock_exclusive(&self) -> Option<Self::ExclusiveGuard>;
unsafe fn unlock_exclusive(&self, guard: Self::ExclusiveGuard);
fn is_locked(&self) -> bool;
fn is_locked_exclusive(&self) -> bool;
}
pub unsafe trait RawRwLockFair: RawRwLock {
unsafe fn unlock_shared_fair(&self, guard: Self::SharedGuard);
unsafe fn unlock_exclusive_fair(&self, guard: Self::ExclusiveGuard);
unsafe fn bump_shared(&self, guard: &mut Self::SharedGuard) {
let state = unsafe { ptr::read(guard) };
defer!(abort_on_panic(|| unsafe {
ptr::write(guard, self.lock_shared())
}));
unsafe { self.unlock_shared_fair(state) };
}
unsafe fn bump_exclusive(&self, guard: &mut Self::ExclusiveGuard) {
let state = unsafe { ptr::read(guard) };
defer!(abort_on_panic(|| unsafe {
ptr::write(guard, self.lock_exclusive())
}));
unsafe { self.unlock_exclusive_fair(state) };
}
}
pub unsafe trait RawRwLockDowngrade: RawRwLock {
unsafe fn downgrade(&self, guard: Self::ExclusiveGuard) -> Self::SharedGuard;
}
pub unsafe trait RawRwLockTimed: RawRwLock {
type Duration;
type Instant;
fn try_lock_shared_for(&self, timeout: Self::Duration) -> Option<Self::SharedGuard>;
fn try_lock_shared_until(&self, timeout: Self::Instant) -> Option<Self::SharedGuard>;
fn try_lock_exclusive_for(&self, timeout: Self::Duration) -> Option<Self::ExclusiveGuard>;
fn try_lock_exclusive_until(&self, timeout: Self::Instant) -> Option<Self::ExclusiveGuard>;
}
pub unsafe trait RawRwLockUpgrade: RawRwLock {
type UpgradableGuard;
fn lock_upgradable(&self) -> Self::UpgradableGuard;
fn try_lock_upgradable(&self) -> Option<Self::UpgradableGuard>;
unsafe fn unlock_upgradable(&self, guard: Self::UpgradableGuard);
unsafe fn upgrade(&self, guard: Self::UpgradableGuard) -> Self::ExclusiveGuard;
unsafe fn try_upgrade(
&self,
guard: Self::UpgradableGuard,
) -> Result<Self::ExclusiveGuard, Self::UpgradableGuard>;
}
pub unsafe trait RawRwLockUpgradeFair: RawRwLockUpgrade + RawRwLockFair {
unsafe fn unlock_upgradable_fair(&self, guard: Self::UpgradableGuard);
unsafe fn bump_upgradable(&self, guard: &mut Self::UpgradableGuard) {
let state = unsafe { ptr::read(guard) };
defer!(abort_on_panic(|| unsafe {
ptr::write(guard, self.lock_upgradable())
}));
unsafe { self.unlock_upgradable_fair(state) };
}
}
pub unsafe trait RawRwLockUpgradeDowngrade: RawRwLockUpgrade + RawRwLockDowngrade {
unsafe fn downgrade_upgradable(&self, guard: Self::UpgradableGuard) -> Self::SharedGuard;
unsafe fn downgrade_to_upgradable(&self, guard: Self::ExclusiveGuard) -> Self::UpgradableGuard;
}
pub unsafe trait RawRwLockUpgradeTimed: RawRwLockUpgrade + RawRwLockTimed {
fn try_lock_upgradable_for(&self, timeout: Self::Duration) -> Option<Self::UpgradableGuard>;
fn try_lock_upgradable_until(&self, timeout: Self::Instant) -> Option<Self::UpgradableGuard>;
unsafe fn try_upgrade_for(
&self,
guard: Self::UpgradableGuard,
timeout: Self::Duration,
) -> Result<Self::ExclusiveGuard, Self::UpgradableGuard>;
unsafe fn try_upgrade_until(
&self,
guard: Self::UpgradableGuard,
timeout: Self::Instant,
) -> Result<Self::ExclusiveGuard, Self::UpgradableGuard>;
}
pub struct RwLock<R, T: ?Sized> {
raw: R,
data: UnsafeCell<T>,
}
#[cfg(feature = "serde")]
impl<R, T> Serialize for RwLock<R, T>
where
R: RawRwLock,
T: Serialize + ?Sized,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.read().serialize(serializer)
}
}
#[cfg(feature = "serde")]
impl<'de, R, T> Deserialize<'de> for RwLock<R, T>
where
R: RawRwLock,
T: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
Deserialize::deserialize(deserializer).map(RwLock::new)
}
}
unsafe impl<R: RawRwLock + Sync, T: ?Sized + Send + Sync> Sync for RwLock<R, T> {}
impl<R: RawRwLock, T> RwLock<R, T> {
#[inline]
pub const fn new(val: T) -> RwLock<R, T> {
RwLock {
data: UnsafeCell::new(val),
raw: R::INIT,
}
}
#[inline]
#[allow(unused_unsafe)]
pub fn into_inner(self) -> T {
unsafe { self.data.into_inner() }
}
}
impl<R, T> RwLock<R, T> {
#[inline]
pub const fn from_raw(raw_rwlock: R, val: T) -> RwLock<R, T> {
RwLock {
data: UnsafeCell::new(val),
raw: raw_rwlock,
}
}
#[inline]
pub fn into_inner_with_raw(self) -> (R, T) {
(self.raw, self.data.into_inner())
}
}
impl<R: RawRwLock, T: ?Sized> RwLock<R, T> {
#[inline]
pub unsafe fn make_read_guard_unchecked(
&self,
guard: R::SharedGuard,
) -> RwLockReadGuard<'_, R, T> {
RwLockReadGuard {
rwlock: self,
marker: PhantomData,
guard: ManuallyDrop::new(guard),
}
}
#[inline]
pub unsafe fn make_write_guard_unchecked(
&self,
guard: R::ExclusiveGuard,
) -> RwLockWriteGuard<'_, R, T> {
RwLockWriteGuard {
rwlock: self,
marker: PhantomData,
guard: ManuallyDrop::new(guard),
}
}
#[inline]
#[track_caller]
pub fn read(&self) -> RwLockReadGuard<'_, R, T> {
let guard = self.raw.lock_shared();
unsafe { self.make_read_guard_unchecked(guard) }
}
#[inline]
#[track_caller]
pub fn try_read(&self) -> Option<RwLockReadGuard<'_, R, T>> {
if let Some(guard) = self.raw.try_lock_shared() {
Some(unsafe { self.make_read_guard_unchecked(guard) })
} else {
None
}
}
#[inline]
#[track_caller]
pub fn write(&self) -> RwLockWriteGuard<'_, R, T> {
let guard = self.raw.lock_exclusive();
unsafe { self.make_write_guard_unchecked(guard) }
}
#[inline]
#[track_caller]
pub fn try_write(&self) -> Option<RwLockWriteGuard<'_, R, T>> {
if let Some(guard) = self.raw.try_lock_exclusive() {
Some(unsafe { self.make_write_guard_unchecked(guard) })
} else {
None
}
}
#[inline]
pub const fn get_mut(&mut self) -> &mut T {
self.data.get_mut()
}
#[inline]
#[track_caller]
pub fn is_locked(&self) -> bool {
self.raw.is_locked()
}
#[inline]
#[track_caller]
pub fn is_locked_exclusive(&self) -> bool {
self.raw.is_locked_exclusive()
}
#[inline]
#[track_caller]
pub unsafe fn force_unlock_read(&self, guard: R::SharedGuard) {
unsafe { self.raw.unlock_shared(guard) };
}
#[inline]
#[track_caller]
pub unsafe fn force_unlock_write(&self, guard: R::ExclusiveGuard) {
unsafe { self.raw.unlock_exclusive(guard) };
}
pub unsafe fn raw(&self) -> &R {
&self.raw
}
#[inline]
pub const fn data_ptr(&self) -> *mut T {
self.data.get()
}
#[cfg(feature = "arc_lock")]
#[inline]
pub unsafe fn make_arc_read_guard_unchecked(
self: &Arc<Self>,
guard: R::SharedGuard,
) -> ArcRwLockReadGuard<R, T> {
ArcRwLockReadGuard {
rwlock: self.clone(),
guard: ManuallyDrop::new(guard),
}
}
#[cfg(feature = "arc_lock")]
#[inline]
pub unsafe fn make_arc_write_guard_unchecked(
self: &Arc<Self>,
guard: R::ExclusiveGuard,
) -> ArcRwLockWriteGuard<R, T> {
ArcRwLockWriteGuard {
rwlock: self.clone(),
guard: ManuallyDrop::new(guard),
}
}
#[cfg(feature = "arc_lock")]
#[inline]
#[track_caller]
pub fn read_arc(self: &Arc<Self>) -> ArcRwLockReadGuard<R, T> {
let guard = self.raw.lock_shared();
unsafe { self.make_arc_read_guard_unchecked(guard) }
}
#[cfg(feature = "arc_lock")]
#[inline]
#[track_caller]
pub fn try_read_arc(self: &Arc<Self>) -> Option<ArcRwLockReadGuard<R, T>> {
if let Some(guard) = self.raw.try_lock_shared() {
Some(unsafe { self.make_arc_read_guard_unchecked(guard) })
} else {
None
}
}
#[cfg(feature = "arc_lock")]
#[inline]
#[track_caller]
pub fn write_arc(self: &Arc<Self>) -> ArcRwLockWriteGuard<R, T> {
let guard = self.raw.lock_exclusive();
unsafe { self.make_arc_write_guard_unchecked(guard) }
}
#[cfg(feature = "arc_lock")]
#[inline]
#[track_caller]
pub fn try_write_arc(self: &Arc<Self>) -> Option<ArcRwLockWriteGuard<R, T>> {
if let Some(guard) = self.raw.try_lock_exclusive() {
Some(unsafe { self.make_arc_write_guard_unchecked(guard) })
} else {
None
}
}
}
impl<R: RawRwLockFair, T: ?Sized> RwLock<R, T> {
#[inline]
#[track_caller]
pub unsafe fn force_unlock_read_fair(&self, guard: R::SharedGuard) {
unsafe { self.raw.unlock_shared_fair(guard) };
}
#[inline]
#[track_caller]
pub unsafe fn force_unlock_write_fair(&self, guard: R::ExclusiveGuard) {
unsafe { self.raw.unlock_exclusive_fair(guard) };
}
}
impl<R: RawRwLockTimed, T: ?Sized> RwLock<R, T> {
#[inline]
#[track_caller]
pub fn try_read_for(&self, timeout: R::Duration) -> Option<RwLockReadGuard<'_, R, T>> {
if let Some(guard) = self.raw.try_lock_shared_for(timeout) {
Some(unsafe { self.make_read_guard_unchecked(guard) })
} else {
None
}
}
#[inline]
#[track_caller]
pub fn try_read_until(&self, timeout: R::Instant) -> Option<RwLockReadGuard<'_, R, T>> {
if let Some(guard) = self.raw.try_lock_shared_until(timeout) {
Some(unsafe { self.make_read_guard_unchecked(guard) })
} else {
None
}
}
#[inline]
#[track_caller]
pub fn try_write_for(&self, timeout: R::Duration) -> Option<RwLockWriteGuard<'_, R, T>> {
if let Some(guard) = self.raw.try_lock_exclusive_for(timeout) {
Some(unsafe { self.make_write_guard_unchecked(guard) })
} else {
None
}
}
#[inline]
#[track_caller]
pub fn try_write_until(&self, timeout: R::Instant) -> Option<RwLockWriteGuard<'_, R, T>> {
if let Some(guard) = self.raw.try_lock_exclusive_until(timeout) {
Some(unsafe { self.make_write_guard_unchecked(guard) })
} else {
None
}
}
#[cfg(feature = "arc_lock")]
#[inline]
#[track_caller]
pub fn try_read_arc_for(
self: &Arc<Self>,
timeout: R::Duration,
) -> Option<ArcRwLockReadGuard<R, T>> {
if let Some(guard) = self.raw.try_lock_shared_for(timeout) {
Some(unsafe { self.make_arc_read_guard_unchecked(guard) })
} else {
None
}
}
#[cfg(feature = "arc_lock")]
#[inline]
#[track_caller]
pub fn try_read_arc_until(
self: &Arc<Self>,
timeout: R::Instant,
) -> Option<ArcRwLockReadGuard<R, T>> {
if let Some(guard) = self.raw.try_lock_shared_until(timeout) {
Some(unsafe { self.make_arc_read_guard_unchecked(guard) })
} else {
None
}
}
#[cfg(feature = "arc_lock")]
#[inline]
#[track_caller]
pub fn try_write_arc_for(
self: &Arc<Self>,
timeout: R::Duration,
) -> Option<ArcRwLockWriteGuard<R, T>> {
if let Some(guard) = self.raw.try_lock_exclusive_for(timeout) {
Some(unsafe { self.make_arc_write_guard_unchecked(guard) })
} else {
None
}
}
#[cfg(feature = "arc_lock")]
#[inline]
#[track_caller]
pub fn try_write_arc_until(
self: &Arc<Self>,
timeout: R::Instant,
) -> Option<ArcRwLockWriteGuard<R, T>> {
if let Some(guard) = self.raw.try_lock_exclusive_until(timeout) {
Some(unsafe { self.make_arc_write_guard_unchecked(guard) })
} else {
None
}
}
}
impl<R: RawRwLockUpgrade, T: ?Sized> RwLock<R, T> {
#[inline]
pub unsafe fn make_upgradable_guard_unchecked(
&self,
guard: R::UpgradableGuard,
) -> RwLockUpgradableReadGuard<'_, R, T> {
RwLockUpgradableReadGuard {
rwlock: self,
marker: PhantomData,
guard: ManuallyDrop::new(guard),
}
}
#[inline]
#[track_caller]
pub fn upgradable_read(&self) -> RwLockUpgradableReadGuard<'_, R, T> {
let guard = self.raw.lock_upgradable();
unsafe { self.make_upgradable_guard_unchecked(guard) }
}
#[inline]
#[track_caller]
pub fn try_upgradable_read(&self) -> Option<RwLockUpgradableReadGuard<'_, R, T>> {
if let Some(guard) = self.raw.try_lock_upgradable() {
Some(unsafe { self.make_upgradable_guard_unchecked(guard) })
} else {
None
}
}
#[cfg(feature = "arc_lock")]
#[inline]
pub unsafe fn make_upgradable_arc_guard_unchecked(
self: &Arc<Self>,
guard: R::UpgradableGuard,
) -> ArcRwLockUpgradableReadGuard<R, T> {
ArcRwLockUpgradableReadGuard {
rwlock: self.clone(),
guard: ManuallyDrop::new(guard),
}
}
#[cfg(feature = "arc_lock")]
#[inline]
#[track_caller]
pub fn upgradable_read_arc(self: &Arc<Self>) -> ArcRwLockUpgradableReadGuard<R, T> {
let guard = self.raw.lock_upgradable();
unsafe { self.make_upgradable_arc_guard_unchecked(guard) }
}
#[cfg(feature = "arc_lock")]
#[inline]
#[track_caller]
pub fn try_upgradable_read_arc(self: &Arc<Self>) -> Option<ArcRwLockUpgradableReadGuard<R, T>> {
if let Some(guard) = self.raw.try_lock_upgradable() {
Some(unsafe { self.make_upgradable_arc_guard_unchecked(guard) })
} else {
None
}
}
}
impl<R: RawRwLockUpgradeTimed, T: ?Sized> RwLock<R, T> {
#[inline]
#[track_caller]
pub fn try_upgradable_read_for(
&self,
timeout: R::Duration,
) -> Option<RwLockUpgradableReadGuard<'_, R, T>> {
if let Some(guard) = self.raw.try_lock_upgradable_for(timeout) {
Some(unsafe { self.make_upgradable_guard_unchecked(guard) })
} else {
None
}
}
#[inline]
#[track_caller]
pub fn try_upgradable_read_until(
&self,
timeout: R::Instant,
) -> Option<RwLockUpgradableReadGuard<'_, R, T>> {
if let Some(guard) = self.raw.try_lock_upgradable_until(timeout) {
Some(unsafe { self.make_upgradable_guard_unchecked(guard) })
} else {
None
}
}
#[cfg(feature = "arc_lock")]
#[inline]
#[track_caller]
pub fn try_upgradable_read_arc_for(
self: &Arc<Self>,
timeout: R::Duration,
) -> Option<ArcRwLockUpgradableReadGuard<R, T>> {
if let Some(guard) = self.raw.try_lock_upgradable_for(timeout) {
Some(unsafe { self.make_upgradable_arc_guard_unchecked(guard) })
} else {
None
}
}
#[cfg(feature = "arc_lock")]
#[inline]
#[track_caller]
pub fn try_upgradable_read_arc_until(
self: &Arc<Self>,
timeout: R::Instant,
) -> Option<ArcRwLockUpgradableReadGuard<R, T>> {
if let Some(guard) = self.raw.try_lock_upgradable_until(timeout) {
Some(unsafe { self.make_upgradable_arc_guard_unchecked(guard) })
} else {
None
}
}
}
impl<R: RawRwLock, T: Default> Default for RwLock<R, T> {
#[inline]
fn default() -> RwLock<R, T> {
RwLock::new(Default::default())
}
}
impl<R: RawRwLock, T> From<T> for RwLock<R, T> {
#[inline]
fn from(t: T) -> RwLock<R, T> {
RwLock::new(t)
}
}
impl<R: RawRwLock, T: ?Sized + fmt::Debug> fmt::Debug for RwLock<R, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut d = f.debug_struct("RwLock");
match self.try_read() {
Some(guard) => d.field("data", &&*guard),
None => {
d.field("data", &format_args!("<locked>"))
}
};
d.finish()
}
}
#[clippy::has_significant_drop]
#[must_use = "if unused the RwLock will immediately unlock"]
pub struct RwLockReadGuard<'a, R: RawRwLock, T: ?Sized> {
rwlock: &'a RwLock<R, T>,
marker: PhantomData<&'a T>,
guard: ManuallyDrop<R::SharedGuard>,
}
impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> RwLockReadGuard<'a, R, T> {
pub fn rwlock(s: &Self) -> &'a RwLock<R, T> {
s.rwlock
}
#[inline]
pub fn map<U: ?Sized, F>(s: Self, f: F) -> MappedRwLockReadGuard<'a, R, U>
where
F: FnOnce(&T) -> &U,
{
let raw = &s.rwlock.raw;
let data = f(unsafe { s.rwlock.data.get().as_ref_unchecked() });
let guard = unsafe { ptr::read(&s.guard) };
mem::forget(s);
MappedRwLockReadGuard {
raw,
data: SharedGuardData::new(data),
guard,
}
}
#[inline]
pub fn try_map<U: ?Sized, F>(s: Self, f: F) -> Result<MappedRwLockReadGuard<'a, R, U>, Self>
where
F: FnOnce(&T) -> Option<&U>,
{
let raw = &s.rwlock.raw;
let Some(data) = f(unsafe { s.rwlock.data.get().as_ref_unchecked() }) else {
return Err(s);
};
let guard = unsafe { ptr::read(&s.guard) };
mem::forget(s);
Ok(MappedRwLockReadGuard {
raw,
data: SharedGuardData::new(data),
guard,
})
}
#[inline]
pub fn try_map_or_err<U: ?Sized, F, E>(
s: Self,
f: F,
) -> Result<MappedRwLockReadGuard<'a, R, U>, (Self, E)>
where
F: FnOnce(&T) -> Result<&U, E>,
{
let raw = &s.rwlock.raw;
let data = match f(unsafe { s.rwlock.data.get().as_ref_unchecked() }) {
Ok(data) => data,
Err(e) => return Err((s, e)),
};
let guard = unsafe { ptr::read(&s.guard) };
mem::forget(s);
Ok(MappedRwLockReadGuard {
raw,
data: SharedGuardData::new(data),
guard,
})
}
#[inline]
#[track_caller]
pub fn unlocked<F, U>(s: &mut Self, f: F) -> U
where
F: FnOnce() -> U,
{
let state = unsafe { ManuallyDrop::take(&mut s.guard) };
defer!(abort_on_panic(
|| s.guard = ManuallyDrop::new(s.rwlock.raw.lock_shared())
));
unsafe { s.rwlock.raw.unlock_shared(state) };
f()
}
}
impl<'a, R: RawRwLockFair + 'a, T: ?Sized + 'a> RwLockReadGuard<'a, R, T> {
#[inline]
#[track_caller]
pub fn unlock_fair(s: Self) {
let mut s = ManuallyDrop::new(s);
unsafe {
s.rwlock
.raw
.unlock_shared_fair(ManuallyDrop::take(&mut s.guard));
}
}
#[inline]
#[track_caller]
pub fn unlocked_fair<F, U>(s: &mut Self, f: F) -> U
where
F: FnOnce() -> U,
{
let state = unsafe { ManuallyDrop::take(&mut s.guard) };
defer!(abort_on_panic(
|| s.guard = ManuallyDrop::new(s.rwlock.raw.lock_shared())
));
unsafe { s.rwlock.raw.unlock_shared_fair(state) };
f()
}
#[inline]
#[track_caller]
pub fn bump(s: &mut Self) {
unsafe { s.rwlock.raw.bump_shared(&mut s.guard) };
}
}
impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> Deref for RwLockReadGuard<'a, R, T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
unsafe { self.rwlock.data.get().as_ref_unchecked() }
}
}
impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> Drop for RwLockReadGuard<'a, R, T> {
#[inline]
fn drop(&mut self) {
unsafe {
self.rwlock
.raw
.unlock_shared(ManuallyDrop::take(&mut self.guard));
}
}
}
impl<'a, R: RawRwLock + 'a, T: fmt::Debug + ?Sized + 'a> fmt::Debug for RwLockReadGuard<'a, R, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&**self, f)
}
}
impl<'a, R: RawRwLock + 'a, T: fmt::Display + ?Sized + 'a> fmt::Display
for RwLockReadGuard<'a, R, T>
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
(**self).fmt(f)
}
}
#[cfg(feature = "owning_ref")]
unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> StableAddress for RwLockReadGuard<'a, R, T> {}
#[cfg(feature = "arc_lock")]
#[clippy::has_significant_drop]
#[must_use = "if unused the RwLock will immediately unlock"]
pub struct ArcRwLockReadGuard<R: RawRwLock, T: ?Sized> {
guard: ManuallyDrop<R::SharedGuard>,
rwlock: Arc<RwLock<R, T>>,
}
#[cfg(feature = "arc_lock")]
impl<R: RawRwLock, T: ?Sized> ArcRwLockReadGuard<R, T> {
pub fn rwlock(s: &Self) -> &Arc<RwLock<R, T>> {
&s.rwlock
}
#[inline]
pub fn into_arc(s: Self) -> Arc<RwLock<R, T>> {
let mut s = ManuallyDrop::new(s);
let rwlock = unsafe { ptr::read(&s.rwlock) };
let guard = unsafe { ManuallyDrop::take(&mut s.guard) };
unsafe { rwlock.raw.unlock_shared(guard) };
rwlock
}
#[inline]
#[track_caller]
pub fn unlocked<F, U>(s: &mut Self, f: F) -> U
where
F: FnOnce() -> U,
{
let state = unsafe { ManuallyDrop::take(&mut s.guard) };
defer!(abort_on_panic(
|| s.guard = ManuallyDrop::new(s.rwlock.raw.lock_shared())
));
unsafe { s.rwlock.raw.unlock_shared(state) };
f()
}
}
#[cfg(feature = "arc_lock")]
impl<R: RawRwLockFair, T: ?Sized> ArcRwLockReadGuard<R, T> {
#[inline]
#[track_caller]
pub fn unlock_fair(s: Self) {
drop(Self::into_arc_fair(s));
}
#[inline]
pub fn into_arc_fair(s: Self) -> Arc<RwLock<R, T>> {
let mut s = ManuallyDrop::new(s);
let rwlock = unsafe { ptr::read(&s.rwlock) };
let guard = unsafe { ManuallyDrop::take(&mut s.guard) };
unsafe { rwlock.raw.unlock_shared_fair(guard) };
rwlock
}
#[inline]
#[track_caller]
pub fn unlocked_fair<F, U>(s: &mut Self, f: F) -> U
where
F: FnOnce() -> U,
{
let state = unsafe { ManuallyDrop::take(&mut s.guard) };
defer!(abort_on_panic(
|| s.guard = ManuallyDrop::new(s.rwlock.raw.lock_shared())
));
unsafe { s.rwlock.raw.unlock_shared_fair(state) };
f()
}
#[inline]
#[track_caller]
pub fn bump(s: &mut Self) {
unsafe { s.rwlock.raw.bump_shared(&mut s.guard) };
}
}
#[cfg(feature = "arc_lock")]
impl<R: RawRwLock, T: ?Sized> Deref for ArcRwLockReadGuard<R, T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
unsafe { self.rwlock.data.get().as_ref_unchecked() }
}
}
#[cfg(feature = "arc_lock")]
impl<R: RawRwLock, T: ?Sized> Drop for ArcRwLockReadGuard<R, T> {
#[inline]
fn drop(&mut self) {
unsafe {
self.rwlock
.raw
.unlock_shared(ManuallyDrop::take(&mut self.guard));
}
}
}
#[cfg(feature = "arc_lock")]
impl<R: RawRwLock, T: fmt::Debug + ?Sized> fmt::Debug for ArcRwLockReadGuard<R, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&**self, f)
}
}
#[cfg(feature = "arc_lock")]
impl<R: RawRwLock, T: fmt::Display + ?Sized> fmt::Display for ArcRwLockReadGuard<R, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
(**self).fmt(f)
}
}
#[clippy::has_significant_drop]
#[must_use = "if unused the RwLock will immediately unlock"]
pub struct RwLockWriteGuard<'a, R: RawRwLock, T: ?Sized> {
rwlock: &'a RwLock<R, T>,
marker: PhantomData<&'a mut T>,
guard: ManuallyDrop<R::ExclusiveGuard>,
}
impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> RwLockWriteGuard<'a, R, T> {
pub fn rwlock(s: &Self) -> &'a RwLock<R, T> {
s.rwlock
}
#[inline]
pub fn map<U: ?Sized, F>(s: Self, f: F) -> MappedRwLockWriteGuard<'a, R, U>
where
F: FnOnce(&mut T) -> &mut U,
{
let raw = &s.rwlock.raw;
let data = f(unsafe { s.rwlock.data.get().as_mut_unchecked() });
let guard = unsafe { ptr::read(&s.guard) };
mem::forget(s);
MappedRwLockWriteGuard {
raw,
data: ExclusiveGuardData::new(data),
guard,
}
}
#[inline]
pub fn try_map<U: ?Sized, F>(s: Self, f: F) -> Result<MappedRwLockWriteGuard<'a, R, U>, Self>
where
F: FnOnce(&mut T) -> Option<&mut U>,
{
let raw = &s.rwlock.raw;
let Some(data) = f(unsafe { s.rwlock.data.get().as_mut_unchecked() }) else {
return Err(s);
};
let guard = unsafe { ptr::read(&s.guard) };
mem::forget(s);
Ok(MappedRwLockWriteGuard {
raw,
data: ExclusiveGuardData::new(data),
guard,
})
}
#[inline]
pub fn try_map_or_err<U: ?Sized, F, E>(
s: Self,
f: F,
) -> Result<MappedRwLockWriteGuard<'a, R, U>, (Self, E)>
where
F: FnOnce(&mut T) -> Result<&mut U, E>,
{
let raw = &s.rwlock.raw;
let data = match f(unsafe { s.rwlock.data.get().as_mut_unchecked() }) {
Ok(data) => data,
Err(e) => return Err((s, e)),
};
let guard = unsafe { ptr::read(&s.guard) };
mem::forget(s);
Ok(MappedRwLockWriteGuard {
raw,
data: ExclusiveGuardData::new(data),
guard,
})
}
#[inline]
#[track_caller]
pub fn unlocked<F, U>(s: &mut Self, f: F) -> U
where
F: FnOnce() -> U,
{
let state = unsafe { ManuallyDrop::take(&mut s.guard) };
defer!(abort_on_panic(
|| s.guard = ManuallyDrop::new(s.rwlock.raw.lock_exclusive())
));
unsafe { s.rwlock.raw.unlock_exclusive(state) };
f()
}
}
impl<'a, R: RawRwLockDowngrade + 'a, T: ?Sized + 'a> RwLockWriteGuard<'a, R, T> {
#[track_caller]
pub fn downgrade(s: Self) -> RwLockReadGuard<'a, R, T> {
let mut s = ManuallyDrop::new(s);
let guard = unsafe { s.rwlock.raw.downgrade(ManuallyDrop::take(&mut s.guard)) };
RwLockReadGuard {
rwlock: s.rwlock,
guard: ManuallyDrop::new(guard),
marker: PhantomData,
}
}
}
impl<'a, R: RawRwLockUpgradeDowngrade + 'a, T: ?Sized + 'a> RwLockWriteGuard<'a, R, T> {
#[track_caller]
pub fn downgrade_to_upgradable(s: Self) -> RwLockUpgradableReadGuard<'a, R, T> {
let mut s = ManuallyDrop::new(s);
let guard = unsafe {
s.rwlock
.raw
.downgrade_to_upgradable(ManuallyDrop::take(&mut s.guard))
};
RwLockUpgradableReadGuard {
rwlock: s.rwlock,
guard: ManuallyDrop::new(guard),
marker: PhantomData,
}
}
}
impl<'a, R: RawRwLockFair + 'a, T: ?Sized + 'a> RwLockWriteGuard<'a, R, T> {
#[inline]
#[track_caller]
pub fn unlock_fair(s: Self) {
let mut s = ManuallyDrop::new(s);
unsafe {
s.rwlock
.raw
.unlock_exclusive_fair(ManuallyDrop::take(&mut s.guard));
}
}
#[inline]
#[track_caller]
pub fn unlocked_fair<F, U>(s: &mut Self, f: F) -> U
where
F: FnOnce() -> U,
{
let state = unsafe { ManuallyDrop::take(&mut s.guard) };
defer!(abort_on_panic(
|| s.guard = ManuallyDrop::new(s.rwlock.raw.lock_exclusive())
));
unsafe { s.rwlock.raw.unlock_exclusive_fair(state) };
f()
}
#[inline]
#[track_caller]
pub fn bump(s: &mut Self) {
unsafe { s.rwlock.raw.bump_exclusive(&mut s.guard) };
}
}
impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> Deref for RwLockWriteGuard<'a, R, T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
unsafe { self.rwlock.data.get().as_ref_unchecked() }
}
}
impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> DerefMut for RwLockWriteGuard<'a, R, T> {
#[inline]
fn deref_mut(&mut self) -> &mut T {
unsafe { self.rwlock.data.get().as_mut_unchecked() }
}
}
impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> Drop for RwLockWriteGuard<'a, R, T> {
#[inline]
fn drop(&mut self) {
unsafe {
self.rwlock
.raw
.unlock_exclusive(ManuallyDrop::take(&mut self.guard));
}
}
}
impl<'a, R: RawRwLock + 'a, T: fmt::Debug + ?Sized + 'a> fmt::Debug for RwLockWriteGuard<'a, R, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&**self, f)
}
}
impl<'a, R: RawRwLock + 'a, T: fmt::Display + ?Sized + 'a> fmt::Display
for RwLockWriteGuard<'a, R, T>
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
(**self).fmt(f)
}
}
#[cfg(feature = "owning_ref")]
unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> StableAddress for RwLockWriteGuard<'a, R, T> {}
#[cfg(feature = "arc_lock")]
#[clippy::has_significant_drop]
#[must_use = "if unused the RwLock will immediately unlock"]
pub struct ArcRwLockWriteGuard<R: RawRwLock, T: ?Sized> {
guard: ManuallyDrop<R::ExclusiveGuard>,
rwlock: Arc<RwLock<R, T>>,
}
#[cfg(feature = "arc_lock")]
impl<R: RawRwLock, T: ?Sized> ArcRwLockWriteGuard<R, T> {
pub fn rwlock(s: &Self) -> &Arc<RwLock<R, T>> {
&s.rwlock
}
#[inline]
pub fn into_arc(s: Self) -> Arc<RwLock<R, T>> {
let mut s = ManuallyDrop::new(s);
let rwlock = unsafe { ptr::read(&s.rwlock) };
let guard = unsafe { ManuallyDrop::take(&mut s.guard) };
unsafe { rwlock.raw.unlock_exclusive(guard) };
rwlock
}
#[inline]
#[track_caller]
pub fn unlocked<F, U>(s: &mut Self, f: F) -> U
where
F: FnOnce() -> U,
{
let state = unsafe { ManuallyDrop::take(&mut s.guard) };
defer!(abort_on_panic(
|| s.guard = ManuallyDrop::new(s.rwlock.raw.lock_exclusive())
));
unsafe { s.rwlock.raw.unlock_exclusive(state) };
f()
}
}
#[cfg(feature = "arc_lock")]
impl<R: RawRwLockDowngrade, T: ?Sized> ArcRwLockWriteGuard<R, T> {
#[track_caller]
pub fn downgrade(s: Self) -> ArcRwLockReadGuard<R, T> {
let mut s = ManuallyDrop::new(s);
let rwlock = unsafe { ptr::read(&s.rwlock) };
let guard = unsafe { ManuallyDrop::take(&mut s.guard) };
let guard = unsafe { rwlock.raw.downgrade(guard) };
ArcRwLockReadGuard {
rwlock,
guard: ManuallyDrop::new(guard),
}
}
}
#[cfg(feature = "arc_lock")]
impl<R: RawRwLockUpgradeDowngrade, T: ?Sized> ArcRwLockWriteGuard<R, T> {
#[track_caller]
pub fn downgrade_to_upgradable(s: Self) -> ArcRwLockUpgradableReadGuard<R, T> {
let mut s = ManuallyDrop::new(s);
let rwlock = unsafe { ptr::read(&s.rwlock) };
let guard = unsafe { ManuallyDrop::take(&mut s.guard) };
let guard = unsafe { rwlock.raw.downgrade_to_upgradable(guard) };
ArcRwLockUpgradableReadGuard {
rwlock,
guard: ManuallyDrop::new(guard),
}
}
}
#[cfg(feature = "arc_lock")]
impl<R: RawRwLockFair, T: ?Sized> ArcRwLockWriteGuard<R, T> {
#[inline]
#[track_caller]
pub fn unlock_fair(s: Self) {
drop(Self::into_arc_fair(s));
}
#[inline]
pub fn into_arc_fair(s: Self) -> Arc<RwLock<R, T>> {
let mut s = ManuallyDrop::new(s);
let rwlock = unsafe { ptr::read(&s.rwlock) };
let guard = unsafe { ManuallyDrop::take(&mut s.guard) };
unsafe { rwlock.raw.unlock_exclusive_fair(guard) };
rwlock
}
#[inline]
#[track_caller]
pub fn unlocked_fair<F, U>(s: &mut Self, f: F) -> U
where
F: FnOnce() -> U,
{
let state = unsafe { ManuallyDrop::take(&mut s.guard) };
defer!(abort_on_panic(
|| s.guard = ManuallyDrop::new(s.rwlock.raw.lock_exclusive())
));
unsafe { s.rwlock.raw.unlock_exclusive_fair(state) };
f()
}
#[inline]
#[track_caller]
pub fn bump(s: &mut Self) {
unsafe { s.rwlock.raw.bump_exclusive(&mut s.guard) };
}
}
#[cfg(feature = "arc_lock")]
impl<R: RawRwLock, T: ?Sized> Deref for ArcRwLockWriteGuard<R, T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
unsafe { self.rwlock.data.get().as_ref_unchecked() }
}
}
#[cfg(feature = "arc_lock")]
impl<R: RawRwLock, T: ?Sized> DerefMut for ArcRwLockWriteGuard<R, T> {
#[inline]
fn deref_mut(&mut self) -> &mut T {
unsafe { self.rwlock.data.get().as_mut_unchecked() }
}
}
#[cfg(feature = "arc_lock")]
impl<R: RawRwLock, T: ?Sized> Drop for ArcRwLockWriteGuard<R, T> {
#[inline]
fn drop(&mut self) {
unsafe {
self.rwlock
.raw
.unlock_exclusive(ManuallyDrop::take(&mut self.guard));
}
}
}
#[cfg(feature = "arc_lock")]
impl<R: RawRwLock, T: fmt::Debug + ?Sized> fmt::Debug for ArcRwLockWriteGuard<R, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&**self, f)
}
}
#[cfg(feature = "arc_lock")]
impl<R: RawRwLock, T: fmt::Display + ?Sized> fmt::Display for ArcRwLockWriteGuard<R, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
(**self).fmt(f)
}
}
#[clippy::has_significant_drop]
#[must_use = "if unused the RwLock will immediately unlock"]
pub struct RwLockUpgradableReadGuard<'a, R: RawRwLockUpgrade, T: ?Sized> {
rwlock: &'a RwLock<R, T>,
marker: PhantomData<&'a T>,
guard: ManuallyDrop<R::UpgradableGuard>,
}
impl<'a, R: RawRwLockUpgrade + 'a, T: ?Sized + 'a> RwLockUpgradableReadGuard<'a, R, T> {
pub fn rwlock(s: &Self) -> &'a RwLock<R, T> {
s.rwlock
}
#[inline]
#[track_caller]
pub fn unlocked<F, U>(s: &mut Self, f: F) -> U
where
F: FnOnce() -> U,
{
let state = unsafe { ManuallyDrop::take(&mut s.guard) };
defer!(abort_on_panic(
|| s.guard = ManuallyDrop::new(s.rwlock.raw.lock_upgradable())
));
unsafe { s.rwlock.raw.unlock_upgradable(state) };
f()
}
#[track_caller]
pub fn upgrade(s: Self) -> RwLockWriteGuard<'a, R, T> {
let mut s = ManuallyDrop::new(s);
let guard = unsafe { s.rwlock.raw.upgrade(ManuallyDrop::take(&mut s.guard)) };
RwLockWriteGuard {
rwlock: s.rwlock,
guard: ManuallyDrop::new(guard),
marker: PhantomData,
}
}
#[track_caller]
pub fn try_upgrade(s: Self) -> Result<RwLockWriteGuard<'a, R, T>, Self> {
let mut s = ManuallyDrop::new(s);
let result = unsafe { s.rwlock.raw.try_upgrade(ManuallyDrop::take(&mut s.guard)) };
match result {
Ok(guard) => Ok(RwLockWriteGuard {
rwlock: s.rwlock,
guard: ManuallyDrop::new(guard),
marker: PhantomData,
}),
Err(guard) => {
s.guard = ManuallyDrop::new(guard);
Err(ManuallyDrop::into_inner(s))
}
}
}
}
impl<'a, R: RawRwLockUpgradeFair + 'a, T: ?Sized + 'a> RwLockUpgradableReadGuard<'a, R, T> {
#[inline]
#[track_caller]
pub fn unlock_fair(s: Self) {
let mut s = ManuallyDrop::new(s);
unsafe {
s.rwlock
.raw
.unlock_upgradable_fair(ManuallyDrop::take(&mut s.guard));
}
}
#[inline]
#[track_caller]
pub fn unlocked_fair<F, U>(s: &mut Self, f: F) -> U
where
F: FnOnce() -> U,
{
let state = unsafe { ManuallyDrop::take(&mut s.guard) };
defer!(abort_on_panic(
|| s.guard = ManuallyDrop::new(s.rwlock.raw.lock_upgradable())
));
unsafe { s.rwlock.raw.unlock_upgradable_fair(state) };
f()
}
#[inline]
#[track_caller]
pub fn bump(s: &mut Self) {
unsafe { s.rwlock.raw.bump_upgradable(&mut s.guard) };
}
}
impl<'a, R: RawRwLockUpgradeDowngrade + 'a, T: ?Sized + 'a> RwLockUpgradableReadGuard<'a, R, T> {
#[track_caller]
pub fn downgrade(s: Self) -> RwLockReadGuard<'a, R, T> {
let mut s = ManuallyDrop::new(s);
let guard = unsafe {
s.rwlock
.raw
.downgrade_upgradable(ManuallyDrop::take(&mut s.guard))
};
RwLockReadGuard {
rwlock: s.rwlock,
guard: ManuallyDrop::new(guard),
marker: PhantomData,
}
}
#[track_caller]
pub fn with_upgraded<Ret, F: FnOnce(&mut T) -> Ret>(&mut self, f: F) -> Ret {
let guard = abort_on_panic(|| unsafe {
self.rwlock.raw.upgrade(ManuallyDrop::take(&mut self.guard))
});
defer! {
self.guard = ManuallyDrop::new(abort_on_panic(|| unsafe {
self.rwlock.raw.downgrade_to_upgradable(guard)
}));
};
f(unsafe { self.rwlock.data.get().as_mut_unchecked() })
}
#[track_caller]
pub fn try_with_upgraded<Ret, F: FnOnce(&mut T) -> Ret>(&mut self, f: F) -> Option<Ret> {
match abort_on_panic(|| unsafe {
self.rwlock
.raw
.try_upgrade(ManuallyDrop::take(&mut self.guard))
}) {
Ok(guard) => {
defer! {
self.guard = ManuallyDrop::new(abort_on_panic(|| unsafe {
self.rwlock.raw.downgrade_to_upgradable(guard)
}));
};
Some(f(unsafe { self.rwlock.data.get().as_mut_unchecked() }))
}
Err(guard) => {
self.guard = ManuallyDrop::new(guard);
None
}
}
}
}
impl<'a, R: RawRwLockUpgradeTimed + 'a, T: ?Sized + 'a> RwLockUpgradableReadGuard<'a, R, T> {
#[track_caller]
pub fn try_upgrade_for(
s: Self,
timeout: R::Duration,
) -> Result<RwLockWriteGuard<'a, R, T>, Self> {
let mut s = ManuallyDrop::new(s);
let result = unsafe {
s.rwlock
.raw
.try_upgrade_for(ManuallyDrop::take(&mut s.guard), timeout)
};
match result {
Ok(guard) => Ok(RwLockWriteGuard {
rwlock: s.rwlock,
guard: ManuallyDrop::new(guard),
marker: PhantomData,
}),
Err(guard) => {
s.guard = ManuallyDrop::new(guard);
Err(ManuallyDrop::into_inner(s))
}
}
}
#[inline]
#[track_caller]
pub fn try_upgrade_until(
s: Self,
timeout: R::Instant,
) -> Result<RwLockWriteGuard<'a, R, T>, Self> {
let mut s = ManuallyDrop::new(s);
let result = unsafe {
s.rwlock
.raw
.try_upgrade_until(ManuallyDrop::take(&mut s.guard), timeout)
};
match result {
Ok(guard) => Ok(RwLockWriteGuard {
rwlock: s.rwlock,
guard: ManuallyDrop::new(guard),
marker: PhantomData,
}),
Err(guard) => {
s.guard = ManuallyDrop::new(guard);
Err(ManuallyDrop::into_inner(s))
}
}
}
}
impl<'a, R: RawRwLockUpgradeTimed + RawRwLockUpgradeDowngrade + 'a, T: ?Sized + 'a>
RwLockUpgradableReadGuard<'a, R, T>
{
#[track_caller]
pub fn try_with_upgraded_for<Ret, F: FnOnce(&mut T) -> Ret>(
&mut self,
timeout: R::Duration,
f: F,
) -> Option<Ret> {
match abort_on_panic(|| unsafe {
self.rwlock
.raw
.try_upgrade_for(ManuallyDrop::take(&mut self.guard), timeout)
}) {
Ok(guard) => {
defer! {
self.guard = ManuallyDrop::new(abort_on_panic(|| unsafe {
self.rwlock.raw.downgrade_to_upgradable(guard)
}));
};
Some(f(unsafe { self.rwlock.data.get().as_mut_unchecked() }))
}
Err(guard) => {
self.guard = ManuallyDrop::new(guard);
None
}
}
}
#[track_caller]
pub fn try_with_upgraded_until<Ret, F: FnOnce(&mut T) -> Ret>(
&mut self,
timeout: R::Instant,
f: F,
) -> Option<Ret> {
match abort_on_panic(|| unsafe {
self.rwlock
.raw
.try_upgrade_until(ManuallyDrop::take(&mut self.guard), timeout)
}) {
Ok(guard) => {
defer! {
self.guard = ManuallyDrop::new(abort_on_panic(|| unsafe {
self.rwlock.raw.downgrade_to_upgradable(guard)
}));
};
Some(f(unsafe { self.rwlock.data.get().as_mut_unchecked() }))
}
Err(guard) => {
self.guard = ManuallyDrop::new(guard);
None
}
}
}
}
impl<'a, R: RawRwLockUpgrade + 'a, T: ?Sized + 'a> Deref for RwLockUpgradableReadGuard<'a, R, T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
unsafe { self.rwlock.data.get().as_ref_unchecked() }
}
}
impl<'a, R: RawRwLockUpgrade + 'a, T: ?Sized + 'a> Drop for RwLockUpgradableReadGuard<'a, R, T> {
#[inline]
fn drop(&mut self) {
unsafe {
self.rwlock
.raw
.unlock_upgradable(ManuallyDrop::take(&mut self.guard));
}
}
}
impl<'a, R: RawRwLockUpgrade + 'a, T: fmt::Debug + ?Sized + 'a> fmt::Debug
for RwLockUpgradableReadGuard<'a, R, T>
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&**self, f)
}
}
impl<'a, R: RawRwLockUpgrade + 'a, T: fmt::Display + ?Sized + 'a> fmt::Display
for RwLockUpgradableReadGuard<'a, R, T>
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
(**self).fmt(f)
}
}
#[cfg(feature = "owning_ref")]
unsafe impl<'a, R: RawRwLockUpgrade + 'a, T: ?Sized + 'a> StableAddress
for RwLockUpgradableReadGuard<'a, R, T>
{
}
#[cfg(feature = "arc_lock")]
#[clippy::has_significant_drop]
#[must_use = "if unused the RwLock will immediately unlock"]
pub struct ArcRwLockUpgradableReadGuard<R: RawRwLockUpgrade, T: ?Sized> {
guard: ManuallyDrop<R::UpgradableGuard>,
rwlock: Arc<RwLock<R, T>>,
}
#[cfg(feature = "arc_lock")]
impl<R: RawRwLockUpgrade, T: ?Sized> ArcRwLockUpgradableReadGuard<R, T> {
pub fn rwlock(s: &Self) -> &Arc<RwLock<R, T>> {
&s.rwlock
}
#[inline]
pub fn into_arc(s: Self) -> Arc<RwLock<R, T>> {
let mut s = ManuallyDrop::new(s);
let rwlock = unsafe { ptr::read(&s.rwlock) };
let guard = unsafe { ManuallyDrop::take(&mut s.guard) };
unsafe { rwlock.raw.unlock_upgradable(guard) };
rwlock
}
#[inline]
#[track_caller]
pub fn unlocked<F, U>(s: &mut Self, f: F) -> U
where
F: FnOnce() -> U,
{
let state = unsafe { ManuallyDrop::take(&mut s.guard) };
defer!(abort_on_panic(
|| s.guard = ManuallyDrop::new(s.rwlock.raw.lock_upgradable())
));
unsafe { s.rwlock.raw.unlock_upgradable(state) };
f()
}
#[track_caller]
pub fn upgrade(s: Self) -> ArcRwLockWriteGuard<R, T> {
let mut s = ManuallyDrop::new(s);
let rwlock = unsafe { ptr::read(&s.rwlock) };
let guard = unsafe { ManuallyDrop::take(&mut s.guard) };
let guard = unsafe { rwlock.raw.upgrade(guard) };
ArcRwLockWriteGuard {
rwlock,
guard: ManuallyDrop::new(guard),
}
}
#[track_caller]
pub fn try_upgrade(s: Self) -> Result<ArcRwLockWriteGuard<R, T>, Self> {
let mut s = ManuallyDrop::new(s);
let rwlock = unsafe { ptr::read(&s.rwlock) };
let guard = unsafe { ManuallyDrop::take(&mut s.guard) };
match unsafe { rwlock.raw.try_upgrade(guard) } {
Ok(guard) => Ok(ArcRwLockWriteGuard {
rwlock,
guard: ManuallyDrop::new(guard),
}),
Err(guard) => Err(Self {
rwlock,
guard: ManuallyDrop::new(guard),
}),
}
}
}
#[cfg(feature = "arc_lock")]
impl<R: RawRwLockUpgradeFair, T: ?Sized> ArcRwLockUpgradableReadGuard<R, T> {
#[inline]
#[track_caller]
pub fn unlock_fair(s: Self) {
drop(Self::into_arc_fair(s));
}
#[inline]
pub fn into_arc_fair(s: Self) -> Arc<RwLock<R, T>> {
let mut s = ManuallyDrop::new(s);
let rwlock = unsafe { ptr::read(&s.rwlock) };
let guard = unsafe { ManuallyDrop::take(&mut s.guard) };
unsafe { rwlock.raw.unlock_upgradable_fair(guard) };
rwlock
}
#[inline]
#[track_caller]
pub fn unlocked_fair<F, U>(s: &mut Self, f: F) -> U
where
F: FnOnce() -> U,
{
let state = unsafe { ManuallyDrop::take(&mut s.guard) };
defer!(abort_on_panic(
|| s.guard = ManuallyDrop::new(s.rwlock.raw.lock_upgradable())
));
unsafe { s.rwlock.raw.unlock_upgradable_fair(state) };
f()
}
#[inline]
#[track_caller]
pub fn bump(s: &mut Self) {
unsafe { s.rwlock.raw.bump_upgradable(&mut s.guard) };
}
}
#[cfg(feature = "arc_lock")]
impl<R: RawRwLockUpgradeDowngrade, T: ?Sized> ArcRwLockUpgradableReadGuard<R, T> {
#[track_caller]
pub fn downgrade(s: Self) -> ArcRwLockReadGuard<R, T> {
let mut s = ManuallyDrop::new(s);
let rwlock = unsafe { ptr::read(&s.rwlock) };
let guard = unsafe { ManuallyDrop::take(&mut s.guard) };
let guard = unsafe { rwlock.raw.downgrade_upgradable(guard) };
ArcRwLockReadGuard {
rwlock,
guard: ManuallyDrop::new(guard),
}
}
#[track_caller]
pub fn with_upgraded<Ret, F: FnOnce(&mut T) -> Ret>(&mut self, f: F) -> Ret {
let guard = abort_on_panic(|| unsafe {
self.rwlock.raw.upgrade(ManuallyDrop::take(&mut self.guard))
});
defer! {
self.guard = ManuallyDrop::new(abort_on_panic(|| unsafe {
self.rwlock.raw.downgrade_to_upgradable(guard)
}));
};
f(unsafe { self.rwlock.data.get().as_mut_unchecked() })
}
#[track_caller]
pub fn try_with_upgraded<Ret, F: FnOnce(&mut T) -> Ret>(&mut self, f: F) -> Option<Ret> {
match abort_on_panic(|| unsafe {
self.rwlock
.raw
.try_upgrade(ManuallyDrop::take(&mut self.guard))
}) {
Ok(guard) => {
defer! {
self.guard = ManuallyDrop::new(abort_on_panic(|| unsafe {
self.rwlock.raw.downgrade_to_upgradable(guard)
}));
};
Some(f(unsafe { self.rwlock.data.get().as_mut_unchecked() }))
}
Err(guard) => {
self.guard = ManuallyDrop::new(guard);
None
}
}
}
}
#[cfg(feature = "arc_lock")]
impl<R: RawRwLockUpgradeTimed, T: ?Sized> ArcRwLockUpgradableReadGuard<R, T> {
#[track_caller]
pub fn try_upgrade_for(
s: Self,
timeout: R::Duration,
) -> Result<ArcRwLockWriteGuard<R, T>, Self> {
let mut s = ManuallyDrop::new(s);
let rwlock = unsafe { ptr::read(&s.rwlock) };
let guard = unsafe { ManuallyDrop::take(&mut s.guard) };
match unsafe { rwlock.raw.try_upgrade_for(guard, timeout) } {
Ok(guard) => Ok(ArcRwLockWriteGuard {
rwlock,
guard: ManuallyDrop::new(guard),
}),
Err(guard) => Err(Self {
rwlock,
guard: ManuallyDrop::new(guard),
}),
}
}
#[inline]
#[track_caller]
pub fn try_upgrade_until(
s: Self,
timeout: R::Instant,
) -> Result<ArcRwLockWriteGuard<R, T>, Self> {
let mut s = ManuallyDrop::new(s);
let rwlock = unsafe { ptr::read(&s.rwlock) };
let guard = unsafe { ManuallyDrop::take(&mut s.guard) };
match unsafe { rwlock.raw.try_upgrade_until(guard, timeout) } {
Ok(guard) => Ok(ArcRwLockWriteGuard {
rwlock,
guard: ManuallyDrop::new(guard),
}),
Err(guard) => Err(Self {
rwlock,
guard: ManuallyDrop::new(guard),
}),
}
}
}
#[cfg(feature = "arc_lock")]
impl<R: RawRwLockUpgradeTimed + RawRwLockUpgradeDowngrade, T: ?Sized>
ArcRwLockUpgradableReadGuard<R, T>
{
#[track_caller]
pub fn try_with_upgraded_for<Ret, F: FnOnce(&mut T) -> Ret>(
&mut self,
timeout: R::Duration,
f: F,
) -> Option<Ret> {
match abort_on_panic(|| unsafe {
self.rwlock
.raw
.try_upgrade_for(ManuallyDrop::take(&mut self.guard), timeout)
}) {
Ok(guard) => {
defer! {
self.guard = ManuallyDrop::new(abort_on_panic(|| unsafe {
self.rwlock.raw.downgrade_to_upgradable(guard)
}));
};
Some(f(unsafe { self.rwlock.data.get().as_mut_unchecked() }))
}
Err(guard) => {
self.guard = ManuallyDrop::new(guard);
None
}
}
}
#[track_caller]
pub fn try_with_upgraded_until<Ret, F: FnOnce(&mut T) -> Ret>(
&mut self,
timeout: R::Instant,
f: F,
) -> Option<Ret> {
match abort_on_panic(|| unsafe {
self.rwlock
.raw
.try_upgrade_until(ManuallyDrop::take(&mut self.guard), timeout)
}) {
Ok(guard) => {
defer! {
self.guard = ManuallyDrop::new(abort_on_panic(|| unsafe {
self.rwlock.raw.downgrade_to_upgradable(guard)
}));
};
Some(f(unsafe { self.rwlock.data.get().as_mut_unchecked() }))
}
Err(guard) => {
self.guard = ManuallyDrop::new(guard);
None
}
}
}
}
#[cfg(feature = "arc_lock")]
impl<R: RawRwLockUpgrade, T: ?Sized> Deref for ArcRwLockUpgradableReadGuard<R, T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
unsafe { self.rwlock.data.get().as_ref_unchecked() }
}
}
#[cfg(feature = "arc_lock")]
impl<R: RawRwLockUpgrade, T: ?Sized> Drop for ArcRwLockUpgradableReadGuard<R, T> {
#[inline]
fn drop(&mut self) {
unsafe {
self.rwlock
.raw
.unlock_upgradable(ManuallyDrop::take(&mut self.guard));
}
}
}
#[cfg(feature = "arc_lock")]
impl<R: RawRwLockUpgrade, T: fmt::Debug + ?Sized> fmt::Debug
for ArcRwLockUpgradableReadGuard<R, T>
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&**self, f)
}
}
#[cfg(feature = "arc_lock")]
impl<R: RawRwLockUpgrade, T: fmt::Display + ?Sized> fmt::Display
for ArcRwLockUpgradableReadGuard<R, T>
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
(**self).fmt(f)
}
}
#[clippy::has_significant_drop]
#[must_use = "if unused the RwLock will immediately unlock"]
pub struct MappedRwLockReadGuard<'a, R: RawRwLock, T: ?Sized + 'a> {
raw: &'a R,
data: SharedGuardData<T>,
guard: ManuallyDrop<R::SharedGuard>,
}
impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> MappedRwLockReadGuard<'a, R, T> {
#[inline]
pub fn map<U: ?Sized, F>(s: Self, f: F) -> MappedRwLockReadGuard<'a, R, U>
where
F: FnOnce(&T) -> &U,
{
let raw = s.raw;
let data = SharedGuardData::new(f(unsafe { s.data.as_ref() }));
let guard = unsafe { ptr::read(&s.guard) };
mem::forget(s);
MappedRwLockReadGuard { raw, data, guard }
}
#[inline]
pub fn try_map<U: ?Sized, F>(s: Self, f: F) -> Result<MappedRwLockReadGuard<'a, R, U>, Self>
where
F: FnOnce(&T) -> Option<&U>,
{
let raw = s.raw;
let Some(data) = f(unsafe { s.data.as_ref() }) else {
return Err(s);
};
let data = SharedGuardData::new(data);
let guard = unsafe { ptr::read(&s.guard) };
mem::forget(s);
Ok(MappedRwLockReadGuard { raw, data, guard })
}
#[inline]
pub fn try_map_or_err<U: ?Sized, F, E>(
s: Self,
f: F,
) -> Result<MappedRwLockReadGuard<'a, R, U>, (Self, E)>
where
F: FnOnce(&T) -> Result<&U, E>,
{
let raw = s.raw;
let data = match f(unsafe { s.data.as_ref() }) {
Ok(data) => data,
Err(e) => return Err((s, e)),
};
let data = SharedGuardData::new(data);
let guard = unsafe { ptr::read(&s.guard) };
mem::forget(s);
Ok(MappedRwLockReadGuard { raw, data, guard })
}
}
impl<'a, R: RawRwLockFair + 'a, T: ?Sized + 'a> MappedRwLockReadGuard<'a, R, T> {
#[inline]
#[track_caller]
pub fn unlock_fair(s: Self) {
let mut s = ManuallyDrop::new(s);
unsafe {
s.raw.unlock_shared_fair(ManuallyDrop::take(&mut s.guard));
}
}
}
impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> Deref for MappedRwLockReadGuard<'a, R, T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
unsafe { self.data.as_ref() }
}
}
impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> Drop for MappedRwLockReadGuard<'a, R, T> {
#[inline]
fn drop(&mut self) {
unsafe {
self.raw.unlock_shared(ManuallyDrop::take(&mut self.guard));
}
}
}
impl<'a, R: RawRwLock + 'a, T: fmt::Debug + ?Sized + 'a> fmt::Debug
for MappedRwLockReadGuard<'a, R, T>
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&**self, f)
}
}
impl<'a, R: RawRwLock + 'a, T: fmt::Display + ?Sized + 'a> fmt::Display
for MappedRwLockReadGuard<'a, R, T>
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
(**self).fmt(f)
}
}
#[cfg(feature = "owning_ref")]
unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> StableAddress
for MappedRwLockReadGuard<'a, R, T>
{
}
#[clippy::has_significant_drop]
#[must_use = "if unused the RwLock will immediately unlock"]
pub struct MappedRwLockWriteGuard<'a, R: RawRwLock, T: ?Sized + 'a> {
raw: &'a R,
data: ExclusiveGuardData<T>,
guard: ManuallyDrop<R::ExclusiveGuard>,
}
impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> MappedRwLockWriteGuard<'a, R, T> {
#[inline]
pub fn map<U: ?Sized, F>(mut s: Self, f: F) -> MappedRwLockWriteGuard<'a, R, U>
where
F: FnOnce(&mut T) -> &mut U,
{
let raw = s.raw;
let data = ExclusiveGuardData::new(f(unsafe { s.data.as_mut() }));
let guard = unsafe { ptr::read(&s.guard) };
mem::forget(s);
MappedRwLockWriteGuard { raw, data, guard }
}
#[inline]
pub fn try_map<U: ?Sized, F>(
mut s: Self,
f: F,
) -> Result<MappedRwLockWriteGuard<'a, R, U>, Self>
where
F: FnOnce(&mut T) -> Option<&mut U>,
{
let raw = s.raw;
let Some(data) = f(unsafe { s.data.as_mut() }) else {
return Err(s);
};
let data = ExclusiveGuardData::new(data);
let guard = unsafe { ptr::read(&s.guard) };
mem::forget(s);
Ok(MappedRwLockWriteGuard { raw, data, guard })
}
#[inline]
pub fn try_map_or_err<U: ?Sized, F, E>(
mut s: Self,
f: F,
) -> Result<MappedRwLockWriteGuard<'a, R, U>, (Self, E)>
where
F: FnOnce(&mut T) -> Result<&mut U, E>,
{
let raw = s.raw;
let data = match f(unsafe { s.data.as_mut() }) {
Ok(data) => data,
Err(e) => return Err((s, e)),
};
let data = ExclusiveGuardData::new(data);
let guard = unsafe { ptr::read(&s.guard) };
mem::forget(s);
Ok(MappedRwLockWriteGuard { raw, data, guard })
}
}
impl<'a, R: RawRwLockFair + 'a, T: ?Sized + 'a> MappedRwLockWriteGuard<'a, R, T> {
#[inline]
#[track_caller]
pub fn unlock_fair(s: Self) {
let mut s = ManuallyDrop::new(s);
unsafe {
s.raw
.unlock_exclusive_fair(ManuallyDrop::take(&mut s.guard));
}
}
}
impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> Deref for MappedRwLockWriteGuard<'a, R, T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
unsafe { self.data.as_ref() }
}
}
impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> DerefMut for MappedRwLockWriteGuard<'a, R, T> {
#[inline]
fn deref_mut(&mut self) -> &mut T {
unsafe { self.data.as_mut() }
}
}
impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> Drop for MappedRwLockWriteGuard<'a, R, T> {
#[inline]
fn drop(&mut self) {
unsafe {
self.raw
.unlock_exclusive(ManuallyDrop::take(&mut self.guard));
}
}
}
impl<'a, R: RawRwLock + 'a, T: fmt::Debug + ?Sized + 'a> fmt::Debug
for MappedRwLockWriteGuard<'a, R, T>
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&**self, f)
}
}
impl<'a, R: RawRwLock + 'a, T: fmt::Display + ?Sized + 'a> fmt::Display
for MappedRwLockWriteGuard<'a, R, T>
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
(**self).fmt(f)
}
}
#[cfg(feature = "owning_ref")]
unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> StableAddress
for MappedRwLockWriteGuard<'a, R, T>
{
}