use core::cell::UnsafeCell;
use core::fmt;
use core::mem::{self, ManuallyDrop};
use core::ops::{Deref, DerefMut};
use core::ptr::{self, NonNull};
use alloc::sync::Arc;
pub(crate) mod futures;
mod raw;
use self::futures::{
Read, ReadArc, UpgradableRead, UpgradableReadArc, Upgrade, UpgradeArc, Write, WriteArc,
};
use self::raw::{RawRwLock, RawUpgrade};
pub struct RwLock<T: ?Sized> {
raw: RawRwLock,
value: UnsafeCell<T>,
}
unsafe impl<T: Send + ?Sized> Send for RwLock<T> {}
unsafe impl<T: Send + Sync + ?Sized> Sync for RwLock<T> {}
impl<T> RwLock<T> {
#[must_use]
#[inline]
pub const fn new(t: T) -> RwLock<T> {
RwLock {
raw: RawRwLock::new(),
value: UnsafeCell::new(t),
}
}
#[must_use]
#[inline]
pub fn into_inner(self) -> T {
self.value.into_inner()
}
#[inline]
pub fn try_read_arc(self: &Arc<Self>) -> Option<RwLockReadGuardArc<T>> {
if self.raw.try_read() {
let arc = self.clone();
Some(unsafe { RwLockReadGuardArc::from_arc(arc) })
} else {
None
}
}
#[inline]
pub fn read_arc<'a>(self: &'a Arc<Self>) -> ReadArc<'a, T> {
ReadArc::new(self.raw.read(), self)
}
#[cfg(all(feature = "std", not(target_family = "wasm")))]
#[inline]
pub fn read_arc_blocking(self: &Arc<Self>) -> RwLockReadGuardArc<T> {
self.read_arc().wait()
}
}
impl<T: ?Sized> RwLock<T> {
#[inline]
pub fn try_read(&self) -> Option<RwLockReadGuard<'_, T>> {
if self.raw.try_read() {
Some(RwLockReadGuard {
lock: &self.raw,
value: self.value.get(),
})
} else {
None
}
}
#[inline]
pub fn read(&self) -> Read<'_, T> {
Read::new(self.raw.read(), self.value.get())
}
#[cfg(all(feature = "std", not(target_family = "wasm")))]
#[inline]
pub fn read_blocking(&self) -> RwLockReadGuard<'_, T> {
self.read().wait()
}
#[inline]
pub fn try_upgradable_read(&self) -> Option<RwLockUpgradableReadGuard<'_, T>> {
if self.raw.try_upgradable_read() {
Some(RwLockUpgradableReadGuard {
lock: &self.raw,
value: self.value.get(),
})
} else {
None
}
}
#[inline]
pub fn upgradable_read(&self) -> UpgradableRead<'_, T> {
UpgradableRead::new(self.raw.upgradable_read(), self.value.get())
}
#[cfg(all(feature = "std", not(target_family = "wasm")))]
#[inline]
pub fn upgradable_read_blocking(&self) -> RwLockUpgradableReadGuard<'_, T> {
self.upgradable_read().wait()
}
#[cfg(all(feature = "std", not(target_family = "wasm")))]
#[inline]
pub fn upgradable_read_arc_blocking(self: &Arc<Self>) -> RwLockUpgradableReadGuardArc<T> {
self.upgradable_read_arc().wait()
}
#[inline]
pub fn try_upgradable_read_arc(self: &Arc<Self>) -> Option<RwLockUpgradableReadGuardArc<T>> {
if self.raw.try_upgradable_read() {
Some(RwLockUpgradableReadGuardArc { lock: self.clone() })
} else {
None
}
}
#[inline]
pub fn upgradable_read_arc<'a>(self: &'a Arc<Self>) -> UpgradableReadArc<'a, T> {
UpgradableReadArc::new(self.raw.upgradable_read(), self)
}
#[inline]
pub fn try_write(&self) -> Option<RwLockWriteGuard<'_, T>> {
if self.raw.try_write() {
Some(RwLockWriteGuard {
lock: &self.raw,
value: self.value.get(),
})
} else {
None
}
}
#[inline]
pub fn write(&self) -> Write<'_, T> {
Write::new(self.raw.write(), self.value.get())
}
#[cfg(all(feature = "std", not(target_family = "wasm")))]
#[inline]
pub fn write_blocking(&self) -> RwLockWriteGuard<'_, T> {
self.write().wait()
}
#[inline]
pub fn try_write_arc(self: &Arc<Self>) -> Option<RwLockWriteGuardArc<T>> {
if self.raw.try_write() {
Some(RwLockWriteGuardArc { lock: self.clone() })
} else {
None
}
}
#[inline]
pub fn write_arc<'a>(self: &'a Arc<Self>) -> WriteArc<'a, T> {
WriteArc::new(self.raw.write(), self)
}
#[cfg(all(feature = "std", not(target_family = "wasm")))]
#[inline]
pub fn write_arc_blocking(self: &Arc<Self>) -> RwLockWriteGuardArc<T> {
self.write_arc().wait()
}
#[must_use]
#[inline]
pub fn get_mut(&mut self) -> &mut T {
unsafe { &mut *self.value.get() }
}
}
impl<T: fmt::Debug + ?Sized> fmt::Debug for RwLock<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
struct Locked;
impl fmt::Debug for Locked {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("<locked>")
}
}
match self.try_read() {
None => f.debug_struct("RwLock").field("value", &Locked).finish(),
Some(guard) => f.debug_struct("RwLock").field("value", &&*guard).finish(),
}
}
}
impl<T> From<T> for RwLock<T> {
#[inline]
fn from(val: T) -> RwLock<T> {
RwLock::new(val)
}
}
impl<T: Default + ?Sized> Default for RwLock<T> {
#[inline]
fn default() -> RwLock<T> {
RwLock::new(Default::default())
}
}
#[clippy::has_significant_drop]
pub struct RwLockReadGuard<'a, T: ?Sized> {
lock: &'a RawRwLock,
value: *const T,
}
unsafe impl<T: Sync + ?Sized> Send for RwLockReadGuard<'_, T> {}
unsafe impl<T: Sync + ?Sized> Sync for RwLockReadGuard<'_, T> {}
impl<T: ?Sized> Drop for RwLockReadGuard<'_, T> {
#[inline]
fn drop(&mut self) {
unsafe {
self.lock.read_unlock();
}
}
}
impl<T: fmt::Debug + ?Sized> fmt::Debug for RwLockReadGuard<'_, T> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&**self, f)
}
}
impl<T: fmt::Display + ?Sized> fmt::Display for RwLockReadGuard<'_, T> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
(**self).fmt(f)
}
}
impl<T: ?Sized> Deref for RwLockReadGuard<'_, T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
unsafe { &*self.value }
}
}
#[clippy::has_significant_drop]
pub struct RwLockReadGuardArc<T> {
lock: NonNull<T>,
}
unsafe impl<T: Send + Sync> Send for RwLockReadGuardArc<T> {}
unsafe impl<T: Send + Sync> Sync for RwLockReadGuardArc<T> {}
impl<T> RwLockReadGuardArc<T> {
#[inline]
unsafe fn inner_arc(guard: &Self) -> ManuallyDrop<Arc<RwLock<T>>> {
ManuallyDrop::new(Arc::from_raw(guard.lock.as_ptr().cast()))
}
#[inline]
unsafe fn from_arc(arc: Arc<RwLock<T>>) -> Self {
let ptr = Arc::into_raw(arc);
Self {
lock: NonNull::new(ptr as *mut RwLock<T> as *mut T).unwrap(),
}
}
}
impl<T> Drop for RwLockReadGuardArc<T> {
#[inline]
fn drop(&mut self) {
unsafe {
let arc = ManuallyDrop::into_inner(Self::inner_arc(self));
arc.raw.read_unlock();
}
}
}
impl<T: fmt::Debug> fmt::Debug for RwLockReadGuardArc<T> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&**self, f)
}
}
impl<T: fmt::Display> fmt::Display for RwLockReadGuardArc<T> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
(**self).fmt(f)
}
}
impl<T> Deref for RwLockReadGuardArc<T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
unsafe {
let arc = Self::inner_arc(self);
&*arc.value.get()
}
}
}
#[clippy::has_significant_drop]
pub struct RwLockUpgradableReadGuard<'a, T: ?Sized> {
lock: &'a RawRwLock,
value: *mut T,
}
impl<'a, T: ?Sized> Drop for RwLockUpgradableReadGuard<'a, T> {
#[inline]
fn drop(&mut self) {
unsafe {
self.lock.upgradable_read_unlock();
}
}
}
unsafe impl<T: Send + Sync + ?Sized> Send for RwLockUpgradableReadGuard<'_, T> {}
unsafe impl<T: Sync + ?Sized> Sync for RwLockUpgradableReadGuard<'_, T> {}
impl<'a, T: ?Sized> RwLockUpgradableReadGuard<'a, T> {
#[inline]
pub fn downgrade(guard: Self) -> RwLockReadGuard<'a, T> {
let upgradable = ManuallyDrop::new(guard);
unsafe {
upgradable.lock.downgrade_upgradable_read();
};
RwLockReadGuard {
lock: upgradable.lock,
value: upgradable.value,
}
}
#[inline]
pub fn try_upgrade(guard: Self) -> Result<RwLockWriteGuard<'a, T>, Self> {
if unsafe { guard.lock.try_upgrade() } {
let reader = ManuallyDrop::new(guard);
Ok(RwLockWriteGuard {
lock: reader.lock,
value: reader.value,
})
} else {
Err(guard)
}
}
#[inline]
pub fn upgrade(guard: Self) -> Upgrade<'a, T> {
let reader = ManuallyDrop::new(guard);
Upgrade::new(
unsafe { reader.lock.upgrade() },
reader.value,
)
}
#[cfg(all(feature = "std", not(target_family = "wasm")))]
#[inline]
pub fn upgrade_blocking(guard: Self) -> RwLockWriteGuard<'a, T> {
RwLockUpgradableReadGuard::upgrade(guard).wait()
}
}
impl<T: fmt::Debug + ?Sized> fmt::Debug for RwLockUpgradableReadGuard<'_, T> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&**self, f)
}
}
impl<T: fmt::Display + ?Sized> fmt::Display for RwLockUpgradableReadGuard<'_, T> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
(**self).fmt(f)
}
}
impl<T: ?Sized> Deref for RwLockUpgradableReadGuard<'_, T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
unsafe { &*self.value }
}
}
#[clippy::has_significant_drop]
pub struct RwLockUpgradableReadGuardArc<T: ?Sized> {
lock: Arc<RwLock<T>>,
}
impl<T: ?Sized> Drop for RwLockUpgradableReadGuardArc<T> {
#[inline]
fn drop(&mut self) {
unsafe {
self.lock.raw.upgradable_read_unlock();
}
}
}
unsafe impl<T: Send + Sync + ?Sized> Send for RwLockUpgradableReadGuardArc<T> {}
unsafe impl<T: Send + Sync + ?Sized> Sync for RwLockUpgradableReadGuardArc<T> {}
impl<T: fmt::Debug + ?Sized> fmt::Debug for RwLockUpgradableReadGuardArc<T> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&**self, f)
}
}
impl<T: fmt::Display + ?Sized> fmt::Display for RwLockUpgradableReadGuardArc<T> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
(**self).fmt(f)
}
}
impl<T: ?Sized> Deref for RwLockUpgradableReadGuardArc<T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
unsafe { &*self.lock.value.get() }
}
}
impl<T> RwLockUpgradableReadGuardArc<T> {
#[inline]
pub fn downgrade(guard: Self) -> RwLockReadGuardArc<T> {
unsafe {
guard.lock.raw.downgrade_upgradable_read();
}
unsafe { RwLockReadGuardArc::from_arc(Self::into_arc(guard)) }
}
}
impl<T: ?Sized> RwLockUpgradableReadGuardArc<T> {
#[inline]
fn into_arc(guard: Self) -> Arc<RwLock<T>> {
let guard = ManuallyDrop::new(guard);
unsafe { ptr::read(&guard.lock) }
}
#[inline]
pub fn try_upgrade(guard: Self) -> Result<RwLockWriteGuardArc<T>, Self> {
if unsafe { guard.lock.raw.try_upgrade() } {
Ok(RwLockWriteGuardArc {
lock: Self::into_arc(guard),
})
} else {
Err(guard)
}
}
#[inline]
pub fn upgrade(guard: Self) -> UpgradeArc<T> {
let raw: RawUpgrade<'_> = unsafe { guard.lock.raw.upgrade() };
let raw: RawUpgrade<'static> = unsafe { mem::transmute(raw) };
unsafe {
UpgradeArc::new(
ManuallyDrop::new(raw),
ManuallyDrop::new(Self::into_arc(guard)),
)
}
}
#[cfg(all(feature = "std", not(target_family = "wasm")))]
#[inline]
pub fn upgrade_blocking(guard: Self) -> RwLockWriteGuardArc<T> {
RwLockUpgradableReadGuardArc::upgrade(guard).wait()
}
}
#[clippy::has_significant_drop]
pub struct RwLockWriteGuard<'a, T: ?Sized> {
lock: &'a RawRwLock,
value: *mut T,
}
unsafe impl<T: Send + ?Sized> Send for RwLockWriteGuard<'_, T> {}
unsafe impl<T: Sync + ?Sized> Sync for RwLockWriteGuard<'_, T> {}
impl<'a, T: ?Sized> Drop for RwLockWriteGuard<'a, T> {
#[inline]
fn drop(&mut self) {
unsafe {
self.lock.write_unlock();
}
}
}
impl<'a, T: ?Sized> RwLockWriteGuard<'a, T> {
#[inline]
pub fn downgrade(guard: Self) -> RwLockReadGuard<'a, T> {
let write = ManuallyDrop::new(guard);
unsafe {
write.lock.downgrade_write();
}
RwLockReadGuard {
lock: write.lock,
value: write.value,
}
}
#[inline]
pub fn downgrade_to_upgradable(guard: Self) -> RwLockUpgradableReadGuard<'a, T> {
let write = ManuallyDrop::new(guard);
unsafe {
write.lock.downgrade_to_upgradable();
}
RwLockUpgradableReadGuard {
lock: write.lock,
value: write.value,
}
}
}
impl<T: fmt::Debug + ?Sized> fmt::Debug for RwLockWriteGuard<'_, T> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&**self, f)
}
}
impl<T: fmt::Display + ?Sized> fmt::Display for RwLockWriteGuard<'_, T> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
(**self).fmt(f)
}
}
impl<T: ?Sized> Deref for RwLockWriteGuard<'_, T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
unsafe { &*self.value }
}
}
impl<T: ?Sized> DerefMut for RwLockWriteGuard<'_, T> {
#[inline]
fn deref_mut(&mut self) -> &mut T {
unsafe { &mut *self.value }
}
}
#[clippy::has_significant_drop]
pub struct RwLockWriteGuardArc<T: ?Sized> {
lock: Arc<RwLock<T>>,
}
unsafe impl<T: Send + Sync + ?Sized> Send for RwLockWriteGuardArc<T> {}
unsafe impl<T: Send + Sync + ?Sized> Sync for RwLockWriteGuardArc<T> {}
impl<T: ?Sized> Drop for RwLockWriteGuardArc<T> {
#[inline]
fn drop(&mut self) {
unsafe {
self.lock.raw.write_unlock();
}
}
}
impl<T> RwLockWriteGuardArc<T> {
#[inline]
pub fn downgrade(guard: Self) -> RwLockReadGuardArc<T> {
unsafe {
guard.lock.raw.downgrade_write();
}
unsafe { RwLockReadGuardArc::from_arc(Self::into_arc(guard)) }
}
}
impl<T: ?Sized> RwLockWriteGuardArc<T> {
#[inline]
fn into_arc(guard: Self) -> Arc<RwLock<T>> {
let guard = ManuallyDrop::new(guard);
unsafe { ptr::read(&guard.lock) }
}
#[inline]
pub fn downgrade_to_upgradable(guard: Self) -> RwLockUpgradableReadGuardArc<T> {
unsafe {
guard.lock.raw.downgrade_to_upgradable();
}
RwLockUpgradableReadGuardArc {
lock: Self::into_arc(guard),
}
}
}
impl<T: fmt::Debug + ?Sized> fmt::Debug for RwLockWriteGuardArc<T> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&**self, f)
}
}
impl<T: fmt::Display + ?Sized> fmt::Display for RwLockWriteGuardArc<T> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
(**self).fmt(f)
}
}
impl<T: ?Sized> Deref for RwLockWriteGuardArc<T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
unsafe { &*self.lock.value.get() }
}
}
impl<T: ?Sized> DerefMut for RwLockWriteGuardArc<T> {
#[inline]
fn deref_mut(&mut self) -> &mut T {
unsafe { &mut *self.lock.value.get() }
}
}