use core::future::Future;
use core::pin::Pin;
use core::task::{Context, Poll};
use core::time::Duration;
use alloc::sync::Arc;
use crate::os::Semaphore;
use crate::os::types::UBaseType;
use crate::traits::SemaphoreFn;
use crate::utils::OsalRsBool;
use super::waker_slot::WakerSlot;
pub struct AsyncSemaphore {
inner: Arc<Semaphore>,
waker: Arc<WakerSlot>,
}
impl AsyncSemaphore {
pub fn new(max_count: u32, initial_count: u32) -> crate::utils::Result<Self> {
let inner = Semaphore::new(
max_count as UBaseType,
initial_count as UBaseType,
)?;
Ok(Self {
inner: Arc::new(inner),
waker: Arc::new(WakerSlot::new()),
})
}
pub fn signal(&self) -> OsalRsBool {
let result = self.inner.signal();
self.waker.wake();
result
}
pub fn wait_async(&self) -> WaitFuture<'_> {
WaitFuture { sem: self }
}
}
pub struct WaitFuture<'a> {
sem: &'a AsyncSemaphore,
}
impl<'a> Future for WaitFuture<'a> {
type Output = OsalRsBool;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
if self.sem.inner.wait(Duration::ZERO) == OsalRsBool::True {
return Poll::Ready(OsalRsBool::True);
}
self.sem.waker.store(cx.waker());
if self.sem.inner.wait(Duration::ZERO) == OsalRsBool::True {
Poll::Ready(OsalRsBool::True)
} else {
Poll::Pending
}
}
}