use crate::sync::AsyncMutex;
use std::future::Future;
use std::marker::PhantomData;
use std::pin::Pin;
use std::task::{Context, Poll};
pub struct WaitLockOfSubscribableMutex<'mutex, T, Mutex>
where
T: 'mutex + ?Sized,
Mutex: AsyncSubscribableMutex<T> + ?Sized,
{
mutex: &'mutex Mutex,
was_called: bool,
phantom_data: PhantomData<T>,
}
impl<'mutex, T, Mutex> WaitLockOfSubscribableMutex<'mutex, T, Mutex>
where
T: 'mutex + ?Sized,
Mutex: AsyncSubscribableMutex<T> + ?Sized,
{
pub fn new(mutex: &'mutex Mutex) -> Self {
WaitLockOfSubscribableMutex {
mutex,
was_called: false,
phantom_data: PhantomData,
}
}
}
impl<'mutex, T, Mutex> Future for WaitLockOfSubscribableMutex<'mutex, T, Mutex>
where
T: 'mutex + ?Sized,
Mutex: AsyncSubscribableMutex<T> + ?Sized,
{
type Output = Mutex::Guard<'mutex>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = unsafe { self.get_unchecked_mut() };
if !this.was_called {
this.was_called = true;
this.mutex.low_level_subscribe(cx);
Poll::Pending
} else {
Poll::Ready(unsafe { this.mutex.get_locked() })
}
}
}
pub trait AsyncSubscribableMutex<T: ?Sized>: AsyncMutex<T> {
fn low_level_subscribe(&self, cx: &Context);
fn subscribe<'mutex>(&'mutex self) -> impl Future<Output = Self::Guard<'mutex>>
where
Self: 'mutex,
T: 'mutex,
{
WaitLockOfSubscribableMutex::new(self)
}
}