use std::cell::UnsafeCell;
use std::marker::PhantomData;
use std::ops::Deref;
use std::ops::DerefMut;
use parking_lot::lock_api::RawRwLock;
#[repr(C)]
pub struct RwLock<T> {
data: UnsafeCell<T>,
lock: parking_lot::RawRwLock,
}
impl<T> RwLock<T> {
#[inline]
pub fn new(data: T) -> Self {
Self {
data: UnsafeCell::new(data),
lock: parking_lot::RawRwLock::INIT,
}
}
#[inline]
pub fn shared(&self) -> RwLockSharedGuard<'_, T> {
self.lock.lock_shared();
RwLockSharedGuard(self, PhantomData)
}
#[inline]
pub fn exclusive(&self) -> RwLockExclusiveGuard<'_, T> {
self.lock.lock_exclusive();
RwLockExclusiveGuard(self, PhantomData)
}
#[inline(always)]
pub fn from_data_ptr(ptr: *const T) -> *const Self {
ptr.cast()
}
}
pub struct RwLockSharedGuard<'a, T>(&'a RwLock<T>, PhantomData<*mut ()>);
impl<T> Deref for RwLockSharedGuard<'_, T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
let ptr = self.0.data.get();
unsafe { &*ptr }
}
}
impl<T> Drop for RwLockSharedGuard<'_, T> {
fn drop(&mut self) {
unsafe { self.0.lock.unlock_shared() }
}
}
pub struct RwLockExclusiveGuard<'a, T>(&'a RwLock<T>, PhantomData<*mut ()>);
impl<T> Deref for RwLockExclusiveGuard<'_, T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
let ptr = self.0.data.get();
unsafe { &*ptr }
}
}
impl<T> DerefMut for RwLockExclusiveGuard<'_, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
let ptr = self.0.data.get();
unsafe { &mut *ptr }
}
}
impl<T> Drop for RwLockExclusiveGuard<'_, T> {
fn drop(&mut self) {
unsafe { self.0.lock.unlock_exclusive() }
}
}
unsafe impl<T: Send> Send for RwLock<T> {}
unsafe impl<T: Send + Sync> Sync for RwLock<T> {}