#[cfg(feature = "alloc")]
mod rw_lock_alloc;
#[cfg(feature = "std")]
mod rw_lock_std;
#[cfg(feature = "alloc")]
pub use rw_lock_alloc::*;
use core::cell::UnsafeCell;
use core::future::Future;
use core::ops::{Deref, DerefMut};
use core::time::Duration;
pub trait TryRwLock<'a> {
type Item: ?Sized;
type ReadGuard: Deref<Target = Self::Item>;
type WriteGuard: DerefMut<Target = Self::Item>;
fn try_read(&'a self) -> Option<Self::ReadGuard>;
fn try_write(&'a self) -> Option<Self::WriteGuard>;
}
pub trait TryRwLockSized<'a>: Sized + TryRwLock<'a> {
fn try_read_func<O>(&'a self, func: impl FnOnce(Option<&Self::Item>) -> O) -> O {
match self.try_read() {
None => func(None),
Some(guard) => func(Some(guard.deref())),
}
}
fn try_write_func<O>(&'a self, func: impl FnOnce(Option<&mut Self::Item>) -> O) -> O {
match self.try_write() {
None => func(None),
Some(mut guard) => func(Some(guard.deref_mut())),
}
}
}
pub trait RwLock<'a>: TryRwLock<'a> {
fn read(&'a self) -> Self::ReadGuard;
fn write(&'a self) -> Self::WriteGuard;
}
pub trait RwLockSized<'a>: Sized + RwLock<'a> + TryRwLockSized<'a> {
fn read_func<O>(&'a self, func: impl FnOnce(&Self::Item) -> O) -> O {
func(self.read().deref())
}
fn write_func<O>(&'a self, func: impl FnOnce(&mut Self::Item) -> O) -> O {
func(self.write().deref_mut())
}
}
pub trait AsyncRwLock<'a>: TryRwLock<'a> {
type AsyncReadGuard: Deref<Target = Self::Item>;
type AsyncWriteGuard: DerefMut<Target = Self::Item>;
type ReadFuture: Future<Output = Self::AsyncReadGuard>;
type WriteFuture: Future<Output = Self::AsyncWriteGuard>;
fn read_async(&'a self) -> Self::ReadFuture;
fn write_async(&'a self) -> Self::WriteFuture;
}
pub trait UpgradeRwLock<'a>: RwLock<'a>
where
Self::ReadGuard: UpgradeReadGuard<'a, Item = Self::Item, WriteGuard = Self::WriteGuard>,
{
}
pub trait AsyncUpgradeRwLock<'a>: AsyncRwLock<'a>
where
Self::AsyncReadGuard:
AsyncUpgradeReadGuard<'a, Item = Self::Item, AsyncWriteGuard = Self::AsyncWriteGuard>,
{
}
pub trait UpgradeReadGuard<'a>: Sized {
type Item: ?Sized;
type WriteGuard: DerefMut<Target = Self::Item>;
fn upgrade(self) -> Self::WriteGuard;
fn try_upgrade(self) -> Result<Self::WriteGuard, Self>;
}
pub trait AsyncUpgradeReadGuard<'a>: Sized {
type Item: ?Sized;
type AsyncWriteGuard: DerefMut<Target = Self::Item>;
type UpgradeFuture: Future<Output = Self::AsyncWriteGuard>;
fn upgrade_async(self) -> Self::UpgradeFuture;
}
pub trait TimeoutRwLock<'a>: RwLock<'a> {
fn read_timeout(&'a self, timeout: Duration) -> Option<Self::ReadGuard>;
fn write_timeout(&'a self, timeout: Duration) -> Option<Self::WriteGuard>;
}
pub trait TimeoutRwLockSized<'a>: Sized + TimeoutRwLock<'a> + RwLockSized<'a> {
fn read_timeout_func<O>(
&'a self,
timeout: Duration,
func: impl FnOnce(Option<&Self::Item>) -> O,
) -> O {
match self.read_timeout(timeout) {
None => func(None),
Some(guard) => func(Some(guard.deref())),
}
}
fn write_timeout_func<O>(
&'a self,
timeout: Duration,
func: impl FnOnce(Option<&mut Self::Item>) -> O,
) -> O {
match self.write_timeout(timeout) {
None => func(None),
Some(mut guard) => func(Some(guard.deref_mut())),
}
}
}
pub trait AsyncTimeoutRwLock<'a>: AsyncRwLock<'a> {
type ReadTimeoutFuture: Future<Output = Option<Self::AsyncReadGuard>>;
type WriteTimeoutFuture: Future<Output = Option<Self::AsyncWriteGuard>>;
fn read_timeout_async(&'a self, timeout: Duration) -> Self::ReadTimeoutFuture;
fn write_timeout_async(&'a self, timeout: Duration) -> Self::WriteTimeoutFuture;
}
pub trait RawTryRwLock {
fn try_add_reader(&self) -> bool;
fn try_add_writer(&self) -> bool;
unsafe fn remove_reader(&self);
unsafe fn remove_writer(&self);
}
pub trait RawRwLock: RawTryRwLock {
fn add_reader(&self);
fn add_writer(&self);
}
pub trait RawTimeoutRwLock: RawRwLock {
fn add_reader_timeout(&self, timeout: Duration) -> bool;
fn add_writer_timeout(&self, timeout: Duration) -> bool;
}
pub trait RawAsyncRwLock: RawTryRwLock {
type AddReaderFuture: Future<Output = ()>;
type AddWriterFuture: Future<Output = ()>;
fn add_reader_async(&self) -> Self::AddReaderFuture;
fn add_writer_async(&self) -> Self::AddWriterFuture;
}
pub trait RawAsyncTimeoutRwLock: RawAsyncRwLock {
type AddReaderTimeoutFuture: Future<Output = bool>;
type AddWriterTimeoutFuture: Future<Output = bool>;
fn add_reader_timeout_async(&self, timeout: Duration) -> Self::AddReaderTimeoutFuture;
fn add_writer_timeout_async(&self, timeout: Duration) -> Self::AddWriterTimeoutFuture;
}
#[derive(Debug)]
pub struct CustomRwLock<T, R> {
data: UnsafeCell<T>,
raw_lock: R,
}
impl<T, R> CustomRwLock<T, R> {
pub fn from_raw(raw_lock: R, data: T) -> Self {
Self {
data: UnsafeCell::new(data),
raw_lock,
}
}
pub fn new(data: T) -> Self
where
R: Default,
{
Self::from_raw(R::default(), data)
}
}
impl<'a, T, R> TryRwLock<'a> for CustomRwLock<T, R>
where
T: 'a,
R: RawTryRwLock + 'a,
{
type Item = T;
type ReadGuard = CustomReadGuard<'a, T, R>;
type WriteGuard = CustomWriteGuard<'a, T, R>;
fn try_read(&'a self) -> Option<Self::ReadGuard> {
match self.raw_lock.try_add_reader() {
true => Some(CustomReadGuard { lock: self }),
false => None,
}
}
fn try_write(&'a self) -> Option<Self::WriteGuard> {
match self.raw_lock.try_add_writer() {
true => Some(CustomWriteGuard { lock: self }),
false => None,
}
}
}
impl<'a, T, R> TryRwLockSized<'a> for CustomRwLock<T, R>
where
T: 'a,
R: RawTryRwLock + 'a,
{
fn try_read_func<O>(&'a self, func: impl FnOnce(Option<&Self::Item>) -> O) -> O {
match self.raw_lock.try_add_reader() {
true => unsafe {
let out = func(Some(&*self.data.get()));
self.raw_lock.remove_reader();
out
},
false => func(None),
}
}
fn try_write_func<O>(&'a self, func: impl FnOnce(Option<&mut Self::Item>) -> O) -> O {
match self.raw_lock.try_add_writer() {
true => unsafe {
let out = func(Some(&mut *self.data.get()));
self.raw_lock.remove_writer();
out
},
false => func(None),
}
}
}
impl<'a, T, R> RwLock<'a> for CustomRwLock<T, R>
where
T: 'a,
R: RawRwLock + 'a,
{
fn read(&'a self) -> Self::ReadGuard {
self.raw_lock.add_reader();
CustomReadGuard { lock: self }
}
fn write(&'a self) -> Self::WriteGuard {
self.raw_lock.add_writer();
CustomWriteGuard { lock: self }
}
}
impl<'a, T, R> RwLockSized<'a> for CustomRwLock<T, R>
where
T: 'a,
R: RawRwLock + 'a,
{
fn read_func<O>(&'a self, func: impl FnOnce(&Self::Item) -> O) -> O {
self.raw_lock.add_reader();
let out = func(unsafe { &*self.data.get() });
unsafe { self.raw_lock.remove_reader() }
out
}
fn write_func<O>(&'a self, func: impl FnOnce(&mut Self::Item) -> O) -> O {
self.raw_lock.add_writer();
let out = func(unsafe { &mut *self.data.get() });
unsafe { self.raw_lock.remove_writer() }
out
}
}
impl<'a, T, R> TimeoutRwLock<'a> for CustomRwLock<T, R>
where
T: 'a,
R: RawTimeoutRwLock + 'a,
{
fn read_timeout(&'a self, timeout: Duration) -> Option<Self::ReadGuard> {
match self.raw_lock.add_reader_timeout(timeout) {
true => Some(CustomReadGuard { lock: self }),
false => None,
}
}
fn write_timeout(&'a self, timeout: Duration) -> Option<Self::WriteGuard> {
match self.raw_lock.add_writer_timeout(timeout) {
true => Some(CustomWriteGuard { lock: self }),
false => None,
}
}
}
impl<'a, T, R> TimeoutRwLockSized<'a> for CustomRwLock<T, R>
where
T: 'a,
R: RawTimeoutRwLock + 'a,
{
fn read_timeout_func<O>(
&'a self,
timeout: Duration,
func: impl FnOnce(Option<&Self::Item>) -> O,
) -> O {
match self.raw_lock.add_reader_timeout(timeout) {
true => unsafe {
let out = func(Some(&*self.data.get()));
self.raw_lock.remove_reader();
out
},
false => func(None),
}
}
fn write_timeout_func<O>(
&'a self,
timeout: Duration,
func: impl FnOnce(Option<&mut Self::Item>) -> O,
) -> O {
match self.raw_lock.add_writer_timeout(timeout) {
true => unsafe {
let out = func(Some(&mut *self.data.get()));
self.raw_lock.remove_writer();
out
},
false => func(None),
}
}
}
#[derive(Debug)]
pub struct CustomReadGuard<'a, T, R>
where
R: RawTryRwLock,
{
lock: &'a CustomRwLock<T, R>,
}
impl<'a, T, R> Deref for CustomReadGuard<'a, T, R>
where
R: RawTryRwLock,
{
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { &*self.lock.data.get() }
}
}
impl<'a, T, R> Drop for CustomReadGuard<'a, T, R>
where
R: RawTryRwLock,
{
fn drop(&mut self) {
unsafe { self.lock.raw_lock.remove_reader() }
}
}
#[derive(Debug)]
pub struct CustomWriteGuard<'a, T, R>
where
R: RawTryRwLock,
{
lock: &'a CustomRwLock<T, R>,
}
impl<'a, T, R> Deref for CustomWriteGuard<'a, T, R>
where
R: RawTryRwLock,
{
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { &*self.lock.data.get() }
}
}
impl<'a, T, R> DerefMut for CustomWriteGuard<'a, T, R>
where
R: RawTryRwLock,
{
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *self.lock.data.get() }
}
}
impl<'a, T, R> Drop for CustomWriteGuard<'a, T, R>
where
R: RawTryRwLock,
{
fn drop(&mut self) {
unsafe { self.lock.raw_lock.remove_writer() }
}
}