use std::cell::UnsafeCell; use std::fmt::Debug; use lock_api::RawRwLock; use crate::key::Keyable; use super::{RwLock, RwLockReadGuard, RwLockReadRef, RwLockWriteGuard, RwLockWriteRef}; impl RwLock { #[must_use] pub const fn new(value: T) -> Self { Self { value: UnsafeCell::new(value), raw: R::INIT, } } } impl Default for RwLock { fn default() -> Self { Self::new(T::default()) } } impl Debug for RwLock { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { // safety: this is just a try lock, and the value is dropped // immediately after, so there's no risk of blocking ourselves // or any other threads if let Some(value) = unsafe { self.try_read_no_key() } { f.debug_struct("RwLock").field("data", &&*value).finish() } else { struct LockedPlaceholder; impl Debug for LockedPlaceholder { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.write_str("") } } f.debug_struct("RwLock") .field("data", &LockedPlaceholder) .finish() } } } impl From for RwLock { fn from(value: T) -> Self { Self::new(value) } } impl AsMut for RwLock { fn as_mut(&mut self) -> &mut T { self.get_mut() } } impl RwLock { pub fn into_inner(self) -> T { self.value.into_inner() } } impl RwLock { pub fn get_mut(&mut self) -> &mut T { self.value.get_mut() } } impl RwLock { pub fn read<'s, 'key: 's, Key: Keyable>( &'s self, key: Key, ) -> RwLockReadGuard<'_, 'key, T, Key, R> { unsafe { self.raw.lock_shared(); // safety: the lock is locked first RwLockReadGuard::new(self, key) } } pub(crate) unsafe fn read_no_key(&self) -> RwLockReadRef<'_, T, R> { self.raw.lock_shared(); // safety: the lock is locked first RwLockReadRef(self) } pub fn try_read<'s, 'key: 's, Key: Keyable>( &'s self, key: Key, ) -> Option> { unsafe { if self.raw.try_lock_shared() { // safety: the lock is locked first Some(RwLockReadGuard::new(self, key)) } else { None } } } pub(crate) unsafe fn try_read_no_key(&self) -> Option> { if self.raw.try_lock_shared() { // safety: the lock is locked first Some(RwLockReadRef(self)) } else { None } } pub fn write<'s, 'key: 's, Key: Keyable>( &'s self, key: Key, ) -> RwLockWriteGuard<'_, 'key, T, Key, R> { unsafe { self.raw.lock_exclusive(); // safety: the lock is locked first RwLockWriteGuard::new(self, key) } } pub(crate) unsafe fn write_no_key(&self) -> RwLockWriteRef<'_, T, R> { self.raw.lock_exclusive(); // safety: the lock is locked first RwLockWriteRef(self) } pub fn try_write<'s, 'key: 's, Key: Keyable>( &'s self, key: Key, ) -> Option> { unsafe { if self.raw.try_lock_exclusive() { // safety: the lock is locked first Some(RwLockWriteGuard::new(self, key)) } else { None } } } pub(crate) unsafe fn try_write_no_key(&self) -> Option> { if self.raw.try_lock_exclusive() { // safety: the lock is locked first Some(RwLockWriteRef(self)) } else { None } } pub(super) unsafe fn force_unlock_read(&self) { self.raw.unlock_shared(); } pub(super) unsafe fn force_unlock_write(&self) { self.raw.unlock_exclusive(); } pub fn unlock_read<'key, Key: Keyable + 'key>( guard: RwLockReadGuard<'_, 'key, T, Key, R>, ) -> Key { unsafe { guard.rwlock.0.force_unlock_read(); } guard.thread_key } pub fn unlock_write<'key, Key: Keyable + 'key>( guard: RwLockWriteGuard<'_, 'key, T, Key, R>, ) -> Key { unsafe { guard.rwlock.0.force_unlock_write(); } guard.thread_key } } unsafe impl Send for RwLock {} unsafe impl Sync for RwLock {}