extern crate alloc;
use super::semaphore;
use crate::sync_types;
use core::ptr;
use core::{convert, future, marker, ops, pin, task};
#[derive(Clone, Copy, Debug)]
pub enum AsyncRwLockError {
StaleRwLock,
MemoryAllocationFailure,
Internal,
}
impl convert::From<semaphore::AsyncSemaphoreError> for AsyncRwLockError {
fn from(value: semaphore::AsyncSemaphoreError) -> Self {
match value {
semaphore::AsyncSemaphoreError::RequestExceedsSemaphoreCapacity => AsyncRwLockError::Internal,
semaphore::AsyncSemaphoreError::StaleSemaphore => AsyncRwLockError::StaleRwLock,
semaphore::AsyncSemaphoreError::MemoryAllocationFailure => AsyncRwLockError::MemoryAllocationFailure,
semaphore::AsyncSemaphoreError::Internal => AsyncRwLockError::Internal,
}
}
}
pub struct AsyncRwLock<ST: sync_types::SyncTypes, T: marker::Send + marker::Sync> {
sem: semaphore::AsyncSemaphore<ST, T>,
}
impl<ST: sync_types::SyncTypes, T: marker::Send + marker::Sync> AsyncRwLock<ST, T> {
pub fn new(data: T) -> Self {
Self {
sem: semaphore::AsyncSemaphore::new(0, data),
}
}
pub fn read<'a, LP: 'a + sync_types::SyncRcPtr<Self>, LR: 'a + sync_types::SyncRcPtrRef<'a, Self, LP>>(
this: &LR,
) -> Result<AsyncRwLockReadFuture<ST, T, LP>, AsyncRwLockError>
where
Self: 'a,
{
let this_sem = sync_types::SyncRcPtrRefForInner::<'_, _, _, _, AsyncRwLockIndexInnerSemTag>::new(this);
let sem_trivial_lease_fut = semaphore::AsyncSemaphore::acquire_leases(&this_sem, 0)?;
Ok(AsyncRwLockReadFuture { sem_trivial_lease_fut })
}
pub fn write<'a, LP: 'a + sync_types::SyncRcPtr<Self>, LR: 'a + sync_types::SyncRcPtrRef<'a, Self, LP>>(
this: &LR,
) -> Result<AsyncRwLockWriteFuture<ST, T, LP>, AsyncRwLockError>
where
Self: 'a,
{
let this_sem = sync_types::SyncRcPtrRefForInner::<'_, _, _, _, AsyncRwLockIndexInnerSemTag>::new(this);
let sem_exclusive_all_fut = semaphore::AsyncSemaphore::acquire_exclusive_all(&this_sem)?;
Ok(AsyncRwLockWriteFuture { sem_exclusive_all_fut })
}
pub fn try_read<'a, LP: 'a + sync_types::SyncRcPtr<Self>, LR: 'a + sync_types::SyncRcPtrRef<'a, Self, LP>>(
this: &LR,
) -> Option<AsyncRwLockReadGuard<ST, T, LP>>
where
Self: 'a,
{
let this_sem = sync_types::SyncRcPtrRefForInner::<'_, _, _, _, AsyncRwLockIndexInnerSemTag>::new(this);
semaphore::AsyncSemaphore::try_acquire_leases(&this_sem, 0)
.unwrap()
.map(|sem_trivial_lease_guard| AsyncRwLockReadGuard {
sem_trivial_lease_guard,
})
}
pub fn try_write<'a, LP: 'a + sync_types::SyncRcPtr<Self>, LR: 'a + sync_types::SyncRcPtrRef<'a, Self, LP>>(
this: &LR,
) -> Option<AsyncRwLockWriteGuard<ST, T, LP>>
where
Self: 'a,
{
let this_sem = sync_types::SyncRcPtrRefForInner::<'_, _, _, _, AsyncRwLockIndexInnerSemTag>::new(this);
semaphore::AsyncSemaphore::try_acquire_exclusive_all(&this_sem).map(|sem_exclusive_all_guard| {
AsyncRwLockWriteGuard {
sem_exclusive_all_guard,
}
})
}
}
struct AsyncRwLockIndexInnerSemTag;
impl<ST: sync_types::SyncTypes, T: marker::Send + marker::Sync> sync_types::DerefInnerByTag<AsyncRwLockIndexInnerSemTag>
for AsyncRwLock<ST, T>
{
crate::impl_deref_inner_by_tag!(sem, semaphore::AsyncSemaphore<ST, T>);
}
pub struct AsyncRwLockReadFuture<
ST: sync_types::SyncTypes,
T: marker::Send + marker::Sync,
LP: sync_types::SyncRcPtr<AsyncRwLock<ST, T>>,
> {
sem_trivial_lease_fut: semaphore::AsyncSemaphoreLeasesFuture<
ST,
T,
sync_types::SyncRcPtrForInner<AsyncRwLock<ST, T>, LP, AsyncRwLockIndexInnerSemTag>,
>,
}
impl<ST: sync_types::SyncTypes, T: marker::Send + marker::Sync, LP: sync_types::SyncRcPtr<AsyncRwLock<ST, T>>>
AsyncRwLockReadFuture<ST, T, LP>
{
pub fn get_rwlock(&self) -> Option<LP> {
self.sem_trivial_lease_fut
.get_semaphore()
.map(|sem| sem.into_container())
}
}
impl<ST: sync_types::SyncTypes, T: marker::Send + marker::Sync, LP: sync_types::SyncRcPtr<AsyncRwLock<ST, T>>>
marker::Unpin for AsyncRwLockReadFuture<ST, T, LP>
{
}
impl<ST: sync_types::SyncTypes, T: marker::Send + marker::Sync, LP: sync_types::SyncRcPtr<AsyncRwLock<ST, T>>>
future::Future for AsyncRwLockReadFuture<ST, T, LP>
{
type Output = Result<AsyncRwLockReadGuard<ST, T, LP>, AsyncRwLockError>;
fn poll(self: pin::Pin<&mut Self>, cx: &mut task::Context<'_>) -> task::Poll<Self::Output> {
future::Future::poll(pin::Pin::new(&mut self.get_mut().sem_trivial_lease_fut), cx)
.map_ok(|sem_trivial_lease_guard| AsyncRwLockReadGuard {
sem_trivial_lease_guard,
})
.map_err(AsyncRwLockError::from)
}
}
pub struct AsyncRwLockReadGuard<
ST: sync_types::SyncTypes,
T: marker::Send + marker::Sync,
LP: sync_types::SyncRcPtr<AsyncRwLock<ST, T>>,
> {
sem_trivial_lease_guard: semaphore::AsyncSemaphoreLeasesGuard<
ST,
T,
sync_types::SyncRcPtrForInner<AsyncRwLock<ST, T>, LP, AsyncRwLockIndexInnerSemTag>,
>,
}
impl<ST: sync_types::SyncTypes, T: marker::Send + marker::Sync, LP: sync_types::SyncRcPtr<AsyncRwLock<ST, T>>>
AsyncRwLockReadGuard<ST, T, LP>
{
pub fn get_rwlock(&self) -> LP::SyncRcPtrRef<'_> {
self.sem_trivial_lease_guard.get_semaphore().get_container().clone()
}
pub fn into_rwlock(self) -> LP {
self.sem_trivial_lease_guard.into_semaphore().into_container()
}
pub fn into_weak(self) -> AsyncRwLockReadWeakGuard<ST, T, LP> {
AsyncRwLockReadWeakGuard {
sem_trivial_lease_guard: Some(self.sem_trivial_lease_guard.into_weak()),
}
}
fn into_raw(this: Self) -> *const T {
let (ptr, leases_granted) = this.sem_trivial_lease_guard.into_raw();
debug_assert_eq!(leases_granted, 0);
ptr
}
unsafe fn from_raw(ptr: *const T) -> Self {
let sem_trivial_lease_guard = unsafe { semaphore::AsyncSemaphoreLeasesGuard::from_raw(ptr, 0) };
Self {
sem_trivial_lease_guard,
}
}
}
impl<ST: sync_types::SyncTypes, T: marker::Send + marker::Sync, LP: sync_types::SyncRcPtr<AsyncRwLock<ST, T>>>
ops::Deref for AsyncRwLockReadGuard<ST, T, LP>
{
type Target = T;
fn deref(&self) -> &Self::Target {
&self.sem_trivial_lease_guard
}
}
impl<ST: sync_types::SyncTypes, T: marker::Send + marker::Sync, LP: sync_types::SyncRcPtr<AsyncRwLock<ST, T>>> Clone
for AsyncRwLockReadGuard<ST, T, LP>
{
fn clone(&self) -> Self {
let sem_trivial_lease_guard = self.sem_trivial_lease_guard.spawn_trivial_lease();
Self {
sem_trivial_lease_guard,
}
}
}
pub struct AsyncRwLockReadWeakGuard<
ST: sync_types::SyncTypes,
T: marker::Send + marker::Sync,
LP: sync_types::SyncRcPtr<AsyncRwLock<ST, T>>,
> {
#[allow(clippy::type_complexity)]
sem_trivial_lease_guard: Option<
semaphore::AsyncSemaphoreLeasesWeakGuard<
ST,
T,
sync_types::SyncRcPtrForInner<AsyncRwLock<ST, T>, LP, AsyncRwLockIndexInnerSemTag>,
>,
>,
}
impl<ST: sync_types::SyncTypes, T: marker::Send + marker::Sync, LP: sync_types::SyncRcPtr<AsyncRwLock<ST, T>>>
AsyncRwLockReadWeakGuard<ST, T, LP>
{
pub fn upgrade(self) -> Option<AsyncRwLockReadGuard<ST, T, LP>> {
self.sem_trivial_lease_guard
.and_then(|sem_trivial_lease_guard| sem_trivial_lease_guard.upgrade())
.map(|sem_trivial_lease_guard| AsyncRwLockReadGuard {
sem_trivial_lease_guard,
})
}
fn upgrade_by_ref(&self) -> Option<AsyncRwLockReadGuard<ST, T, LP>> {
self.sem_trivial_lease_guard
.as_ref()
.and_then(|sem_trivial_lease_guard| sem_trivial_lease_guard.try_spawn_trivial_lease())
.map(|sem_trivial_lease_guard| AsyncRwLockReadGuard {
sem_trivial_lease_guard,
})
}
fn into_raw(mut this: Self) -> *const T {
this.sem_trivial_lease_guard
.take()
.map(|sem_trivial_lease_guard| {
let (ptr, leases_granted) = sem_trivial_lease_guard.into_raw();
debug_assert_eq!(leases_granted, 0);
ptr
})
.unwrap_or(ptr::null())
}
unsafe fn from_raw(ptr: *const T) -> Self {
if !ptr.is_null() {
let sem_trivial_lease_guard = unsafe { semaphore::AsyncSemaphoreLeasesWeakGuard::from_raw(ptr, 0) };
Self {
sem_trivial_lease_guard: Some(sem_trivial_lease_guard),
}
} else {
Self {
sem_trivial_lease_guard: None,
}
}
}
}
impl<ST: sync_types::SyncTypes, T: marker::Send + marker::Sync, LP: sync_types::SyncRcPtr<AsyncRwLock<ST, T>>> Clone
for AsyncRwLockReadWeakGuard<ST, T, LP>
{
fn clone(&self) -> Self {
let sem_trivial_lease_guard = self
.sem_trivial_lease_guard
.as_ref()
.and_then(|sem_trivial_lease_guard| sem_trivial_lease_guard.try_spawn_trivial_lease())
.map(|sem_trivial_lease_guard| sem_trivial_lease_guard.into_weak());
Self {
sem_trivial_lease_guard,
}
}
}
pub struct AsyncRwLockReadGuardForInner<
ST: sync_types::SyncTypes,
OT,
LP: sync_types::SyncRcPtr<AsyncRwLock<ST, OT>>,
TAG,
> where
OT: sync_types::DerefInnerByTag<TAG> + marker::Send + marker::Sync,
<OT as sync_types::DerefInnerByTag<TAG>>::Output: marker::Send + marker::Sync,
{
guard_for_outer: AsyncRwLockReadGuard<ST, OT, LP>,
_phantom: marker::PhantomData<fn() -> TAG>,
}
impl<ST: sync_types::SyncTypes, OT, LP: sync_types::SyncRcPtr<AsyncRwLock<ST, OT>>, TAG> Clone
for AsyncRwLockReadGuardForInner<ST, OT, LP, TAG>
where
OT: sync_types::DerefInnerByTag<TAG> + marker::Send + marker::Sync,
<OT as sync_types::DerefInnerByTag<TAG>>::Output: marker::Send + marker::Sync,
{
fn clone(&self) -> Self {
Self {
guard_for_outer: self.guard_for_outer.clone(),
_phantom: marker::PhantomData,
}
}
}
impl<ST: sync_types::SyncTypes, OT, LP: sync_types::SyncRcPtr<AsyncRwLock<ST, OT>>, TAG>
convert::From<AsyncRwLockReadGuard<ST, OT, LP>> for AsyncRwLockReadGuardForInner<ST, OT, LP, TAG>
where
OT: sync_types::DerefInnerByTag<TAG> + marker::Send + marker::Sync,
<OT as sync_types::DerefInnerByTag<TAG>>::Output: marker::Send + marker::Sync,
{
fn from(value: AsyncRwLockReadGuard<ST, OT, LP>) -> Self {
Self {
guard_for_outer: value,
_phantom: marker::PhantomData,
}
}
}
impl<ST: sync_types::SyncTypes, OT, LP: sync_types::SyncRcPtr<AsyncRwLock<ST, OT>>, TAG> ops::Deref
for AsyncRwLockReadGuardForInner<ST, OT, LP, TAG>
where
OT: sync_types::DerefInnerByTag<TAG> + marker::Send + marker::Sync,
<OT as sync_types::DerefInnerByTag<TAG>>::Output: marker::Send + marker::Sync,
{
type Target = <OT as sync_types::DerefInnerByTag<TAG>>::Output;
fn deref(&self) -> &Self::Target {
<OT as sync_types::DerefInnerByTag<TAG>>::deref_inner(&self.guard_for_outer)
}
}
impl<ST: sync_types::SyncTypes, OT, LP: sync_types::SyncRcPtr<AsyncRwLock<ST, OT>>, TAG>
sync_types::SyncRcPtr<<OT as sync_types::DerefInnerByTag<TAG>>::Output>
for AsyncRwLockReadGuardForInner<ST, OT, LP, TAG>
where
OT: sync_types::DerefInnerByTag<TAG> + marker::Send + marker::Sync,
<OT as sync_types::DerefInnerByTag<TAG>>::Output: marker::Send + marker::Sync,
{
type WeakSyncRcPtr = AsyncRwLockReadWeakGuardForInner<ST, OT, LP, TAG>;
type SyncRcPtrRef<'a>
= sync_types::GenericSyncRcPtrRef<'a, <OT as sync_types::DerefInnerByTag<TAG>>::Output, Self>
where
Self: 'a;
fn downgrade(&self) -> Self::WeakSyncRcPtr {
Self::WeakSyncRcPtr::from(self.guard_for_outer.clone().into_weak())
}
fn into_raw(this: Self) -> *const <OT as sync_types::DerefInnerByTag<TAG>>::Output {
let ptr_to_outer = AsyncRwLockReadGuard::into_raw(this.guard_for_outer);
<OT as sync_types::DerefInnerByTag<TAG>>::to_inner_ptr(ptr_to_outer)
}
unsafe fn from_raw(ptr: *const <OT as sync_types::DerefInnerByTag<TAG>>::Output) -> Self {
let ptr_to_outer = unsafe { <OT as sync_types::DerefInnerByTag<TAG>>::container_of(ptr) };
let guard_for_outer = unsafe { AsyncRwLockReadGuard::from_raw(ptr_to_outer) };
Self {
guard_for_outer,
_phantom: marker::PhantomData,
}
}
}
pub struct AsyncRwLockReadWeakGuardForInner<
ST: sync_types::SyncTypes,
OT,
LP: sync_types::SyncRcPtr<AsyncRwLock<ST, OT>>,
TAG,
> where
OT: sync_types::DerefInnerByTag<TAG> + marker::Send + marker::Sync,
<OT as sync_types::DerefInnerByTag<TAG>>::Output: marker::Send + marker::Sync,
{
guard_for_outer: AsyncRwLockReadWeakGuard<ST, OT, LP>,
_phantom: marker::PhantomData<fn() -> TAG>,
}
impl<ST: sync_types::SyncTypes, OT, LP: sync_types::SyncRcPtr<AsyncRwLock<ST, OT>>, TAG> Clone
for AsyncRwLockReadWeakGuardForInner<ST, OT, LP, TAG>
where
OT: sync_types::DerefInnerByTag<TAG> + marker::Send + marker::Sync,
<OT as sync_types::DerefInnerByTag<TAG>>::Output: marker::Send + marker::Sync,
{
fn clone(&self) -> Self {
Self {
guard_for_outer: self.guard_for_outer.clone(),
_phantom: marker::PhantomData,
}
}
}
impl<ST: sync_types::SyncTypes, OT, LP: sync_types::SyncRcPtr<AsyncRwLock<ST, OT>>, TAG>
convert::From<AsyncRwLockReadWeakGuard<ST, OT, LP>> for AsyncRwLockReadWeakGuardForInner<ST, OT, LP, TAG>
where
OT: sync_types::DerefInnerByTag<TAG> + marker::Send + marker::Sync,
<OT as sync_types::DerefInnerByTag<TAG>>::Output: marker::Send + marker::Sync,
{
fn from(value: AsyncRwLockReadWeakGuard<ST, OT, LP>) -> Self {
Self {
guard_for_outer: value,
_phantom: marker::PhantomData,
}
}
}
impl<ST: sync_types::SyncTypes, OT, LP: sync_types::SyncRcPtr<AsyncRwLock<ST, OT>>, TAG>
sync_types::WeakSyncRcPtr<
<OT as sync_types::DerefInnerByTag<TAG>>::Output,
AsyncRwLockReadGuardForInner<ST, OT, LP, TAG>,
> for AsyncRwLockReadWeakGuardForInner<ST, OT, LP, TAG>
where
OT: sync_types::DerefInnerByTag<TAG> + marker::Send + marker::Sync,
<OT as sync_types::DerefInnerByTag<TAG>>::Output: marker::Send + marker::Sync,
{
fn upgrade(&self) -> Option<AsyncRwLockReadGuardForInner<ST, OT, LP, TAG>> {
self.guard_for_outer
.upgrade_by_ref()
.map(|guard_for_outer| AsyncRwLockReadGuardForInner {
guard_for_outer,
_phantom: marker::PhantomData,
})
}
fn into_raw(this: Self) -> *const <OT as sync_types::DerefInnerByTag<TAG>>::Output {
let ptr_to_outer = AsyncRwLockReadWeakGuard::into_raw(this.guard_for_outer);
<OT as sync_types::DerefInnerByTag<TAG>>::to_inner_ptr(ptr_to_outer)
}
unsafe fn from_raw(ptr: *const <OT as sync_types::DerefInnerByTag<TAG>>::Output) -> Self {
let ptr_to_outer = unsafe { <OT as sync_types::DerefInnerByTag<TAG>>::container_of(ptr) };
let guard_for_outer = unsafe { AsyncRwLockReadWeakGuard::from_raw(ptr_to_outer) };
Self {
guard_for_outer,
_phantom: marker::PhantomData,
}
}
}
pub struct AsyncRwLockWriteFuture<
ST: sync_types::SyncTypes,
T: marker::Send + marker::Sync,
LP: sync_types::SyncRcPtr<AsyncRwLock<ST, T>>,
> {
sem_exclusive_all_fut: semaphore::AsyncSemaphoreExclusiveAllFuture<
ST,
T,
sync_types::SyncRcPtrForInner<AsyncRwLock<ST, T>, LP, AsyncRwLockIndexInnerSemTag>,
>,
}
impl<ST: sync_types::SyncTypes, T: marker::Send + marker::Sync, LP: sync_types::SyncRcPtr<AsyncRwLock<ST, T>>>
AsyncRwLockWriteFuture<ST, T, LP>
{
pub fn get_rwlock(&self) -> Option<LP> {
self.sem_exclusive_all_fut
.get_semaphore()
.map(|sem| sem.into_container())
}
}
impl<ST: sync_types::SyncTypes, T: marker::Send + marker::Sync, LP: sync_types::SyncRcPtr<AsyncRwLock<ST, T>>>
marker::Unpin for AsyncRwLockWriteFuture<ST, T, LP>
{
}
impl<ST: sync_types::SyncTypes, T: marker::Send + marker::Sync, LP: sync_types::SyncRcPtr<AsyncRwLock<ST, T>>>
future::Future for AsyncRwLockWriteFuture<ST, T, LP>
{
type Output = Result<AsyncRwLockWriteGuard<ST, T, LP>, AsyncRwLockError>;
fn poll(self: pin::Pin<&mut Self>, cx: &mut task::Context<'_>) -> task::Poll<Self::Output> {
future::Future::poll(pin::Pin::new(&mut self.get_mut().sem_exclusive_all_fut), cx)
.map_ok(|sem_exclusive_all_guard| AsyncRwLockWriteGuard {
sem_exclusive_all_guard,
})
.map_err(AsyncRwLockError::from)
}
}
pub struct AsyncRwLockWriteGuard<
ST: sync_types::SyncTypes,
T: marker::Send + marker::Sync,
LP: sync_types::SyncRcPtr<AsyncRwLock<ST, T>>,
> {
sem_exclusive_all_guard: semaphore::AsyncSemaphoreExclusiveAllGuard<
ST,
T,
sync_types::SyncRcPtrForInner<AsyncRwLock<ST, T>, LP, AsyncRwLockIndexInnerSemTag>,
>,
}
impl<ST: sync_types::SyncTypes, T: marker::Send + marker::Sync, LP: sync_types::SyncRcPtr<AsyncRwLock<ST, T>>>
AsyncRwLockWriteGuard<ST, T, LP>
{
pub fn get_rwlock(&self) -> LP::SyncRcPtrRef<'_> {
self.sem_exclusive_all_guard.get_semaphore().get_container().clone()
}
pub fn into_rwlock(self) -> LP {
self.sem_exclusive_all_guard.into_semaphore().into_container()
}
pub fn into_weak(self) -> AsyncRwLockWriteWeakGuard<ST, T, LP> {
AsyncRwLockWriteWeakGuard {
sem_exclusive_all_guard: self.sem_exclusive_all_guard.into_weak(),
}
}
pub fn borrow_outer_inner_mut<'a>(&'a mut self) -> (LP::SyncRcPtrRef<'a>, &'a mut T) {
let (sem, v) = self.sem_exclusive_all_guard.borrow_outer_inner_mut();
(sem.get_container().clone(), v)
}
}
impl<ST: sync_types::SyncTypes, T: marker::Send + marker::Sync, LP: sync_types::SyncRcPtr<AsyncRwLock<ST, T>>>
ops::Deref for AsyncRwLockWriteGuard<ST, T, LP>
{
type Target = T;
fn deref(&self) -> &Self::Target {
&self.sem_exclusive_all_guard
}
}
impl<ST: sync_types::SyncTypes, T: marker::Send + marker::Sync, LP: sync_types::SyncRcPtr<AsyncRwLock<ST, T>>>
ops::DerefMut for AsyncRwLockWriteGuard<ST, T, LP>
{
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.sem_exclusive_all_guard
}
}
pub struct AsyncRwLockWriteWeakGuard<
ST: sync_types::SyncTypes,
T: marker::Send + marker::Sync,
LP: sync_types::SyncRcPtr<AsyncRwLock<ST, T>>,
> {
sem_exclusive_all_guard: semaphore::AsyncSemaphoreExclusiveAllWeakGuard<
ST,
T,
sync_types::SyncRcPtrForInner<AsyncRwLock<ST, T>, LP, AsyncRwLockIndexInnerSemTag>,
>,
}
impl<ST: sync_types::SyncTypes, T: marker::Send + marker::Sync, LP: sync_types::SyncRcPtr<AsyncRwLock<ST, T>>>
AsyncRwLockWriteWeakGuard<ST, T, LP>
{
pub fn upgrade(self) -> Option<AsyncRwLockWriteGuard<ST, T, LP>> {
self.sem_exclusive_all_guard
.upgrade()
.map(|sem_exclusive_all_guard| AsyncRwLockWriteGuard {
sem_exclusive_all_guard,
})
}
}