use core::future::Future;
use core::pin::Pin;
use core::task::{Context, Poll};
use core::time::Duration;
use alloc::sync::Arc;
use crate::os::types::{UBaseType, TickType};
use crate::os::Queue;
use crate::traits::QueueFn;
use crate::utils::{Error, Result};
use super::waker_slot::WakerSlot;
pub struct AsyncQueue {
inner: Arc<Queue>,
rx_waker: Arc<WakerSlot>,
tx_waker: Arc<WakerSlot>,
}
impl AsyncQueue {
pub fn new(size: u32, message_size: u32) -> Result<Self> {
let inner = Queue::new(size as UBaseType, message_size as UBaseType)?;
Ok(Self {
inner: Arc::new(inner),
rx_waker: Arc::new(WakerSlot::new()),
tx_waker: Arc::new(WakerSlot::new()),
})
}
pub fn post(&self, item: &[u8], timeout_ms: u64) -> Result<()> {
let ticks = TickType::try_from(
Duration::from_millis(timeout_ms)
.as_millis()
.try_into()
.unwrap_or(TickType::MAX),
)
.unwrap_or(TickType::MAX);
let result = self.inner.post(item, ticks);
if result.is_ok() {
self.rx_waker.wake();
}
result
}
pub fn fetch(&self, buf: &mut [u8], timeout_ms: u64) -> Result<()> {
let ticks = TickType::try_from(
Duration::from_millis(timeout_ms)
.as_millis()
.try_into()
.unwrap_or(TickType::MAX),
)
.unwrap_or(TickType::MAX);
let result = self.inner.fetch(buf, ticks);
if result.is_ok() {
self.tx_waker.wake();
}
result
}
pub fn fetch_async<'a>(&'a self, buf: &'a mut [u8]) -> FetchFuture<'a> {
FetchFuture {
queue: self,
buf,
}
}
pub fn post_async<'a>(&'a self, item: &'a [u8]) -> PostFuture<'a> {
PostFuture {
queue: self,
item,
}
}
}
pub struct FetchFuture<'a> {
queue: &'a AsyncQueue,
buf: &'a mut [u8],
}
impl<'a> Future for FetchFuture<'a> {
type Output = Result<()>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.get_mut();
match this.queue.inner.fetch(this.buf, 0) {
Ok(()) => {
this.queue.tx_waker.wake();
return Poll::Ready(Ok(()));
}
Err(Error::Timeout) => {}
Err(e) => return Poll::Ready(Err(e)),
}
this.queue.rx_waker.store(cx.waker());
match this.queue.inner.fetch(this.buf, 0) {
Ok(()) => {
this.queue.tx_waker.wake();
Poll::Ready(Ok(()))
}
Err(Error::Timeout) => Poll::Pending,
Err(e) => Poll::Ready(Err(e)),
}
}
}
pub struct PostFuture<'a> {
queue: &'a AsyncQueue,
item: &'a [u8],
}
impl<'a> Future for PostFuture<'a> {
type Output = Result<()>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.get_mut();
match this.queue.inner.post(this.item, 0) {
Ok(()) => {
this.queue.rx_waker.wake();
return Poll::Ready(Ok(()));
}
Err(Error::Timeout) => {}
Err(e) => return Poll::Ready(Err(e)),
}
this.queue.tx_waker.store(cx.waker());
match this.queue.inner.post(this.item, 0) {
Ok(()) => {
this.queue.rx_waker.wake();
Poll::Ready(Ok(()))
}
Err(Error::Timeout) => Poll::Pending,
Err(e) => Poll::Ready(Err(e)),
}
}
}