use super::*;
use std::future::{Future, IntoFuture};
use std::pin::Pin;
use std::sync::{Arc, Mutex};
use std::task::{Context, Poll, Waker};
pub trait Async: Interface {
type Output: Clone;
type CompletedHandler: Interface;
fn set_completed<F: Fn() + Send + 'static>(&self, handler: F) -> Result<()>;
fn invoke_completed(&self, handler: &Self::CompletedHandler, status: AsyncStatus);
fn get_results(&self) -> Result<Self::Output>;
}
pub struct AsyncFuture<A: Async> {
inner: A,
status: IAsyncInfo,
waker: Option<Arc<Mutex<Waker>>>,
}
impl<A: Async> AsyncFuture<A> {
fn new(inner: A) -> Self {
Self {
status: inner.cast().unwrap(),
inner,
waker: None,
}
}
}
unsafe impl<A: Async> Send for AsyncFuture<A> {}
unsafe impl<A: Async> Sync for AsyncFuture<A> {}
impl<A: Async> Unpin for AsyncFuture<A> {}
impl<A: Async> Future for AsyncFuture<A> {
type Output = Result<A::Output>;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
if self.status.Status()? != AsyncStatus::Started {
return Poll::Ready(self.inner.get_results());
}
if let Some(shared_waker) = &self.waker {
let mut guard = shared_waker.lock().unwrap();
guard.clone_from(cx.waker());
if self.status.Status()? != AsyncStatus::Started {
return Poll::Ready(self.inner.get_results());
}
} else {
let shared_waker = Arc::new(Mutex::new(cx.waker().clone()));
self.waker = Some(shared_waker.clone());
self.inner.set_completed(move || {
shared_waker.lock().unwrap().wake_by_ref();
})?;
};
Poll::Pending
}
}
impl Async for IAsyncAction {
type Output = ();
type CompletedHandler = AsyncActionCompletedHandler;
fn set_completed<F: Fn() + Send + 'static>(&self, handler: F) -> Result<()> {
self.SetCompleted(&AsyncActionCompletedHandler::new(move |_, _| {
handler();
Ok(())
}))
}
fn invoke_completed(&self, handler: &Self::CompletedHandler, status: AsyncStatus) {
_ = handler.Invoke(self, status);
}
fn get_results(&self) -> Result<Self::Output> {
self.GetResults()
}
}
impl<T: RuntimeType> Async for IAsyncOperation<T> {
type Output = T;
type CompletedHandler = AsyncOperationCompletedHandler<T>;
fn set_completed<F: Fn() + Send + 'static>(&self, handler: F) -> Result<()> {
self.SetCompleted(&AsyncOperationCompletedHandler::new(move |_, _| {
handler();
Ok(())
}))
}
fn invoke_completed(&self, handler: &Self::CompletedHandler, status: AsyncStatus) {
_ = handler.Invoke(self, status);
}
fn get_results(&self) -> Result<Self::Output> {
self.GetResults()
}
}
impl<P: RuntimeType> Async for IAsyncActionWithProgress<P> {
type Output = ();
type CompletedHandler = AsyncActionWithProgressCompletedHandler<P>;
fn set_completed<F: Fn() + Send + 'static>(&self, handler: F) -> Result<()> {
self.SetCompleted(&AsyncActionWithProgressCompletedHandler::new(
move |_, _| {
handler();
Ok(())
},
))
}
fn invoke_completed(&self, handler: &Self::CompletedHandler, status: AsyncStatus) {
_ = handler.Invoke(self, status);
}
fn get_results(&self) -> Result<Self::Output> {
self.GetResults()
}
}
impl<T: RuntimeType, P: RuntimeType> Async for IAsyncOperationWithProgress<T, P> {
type Output = T;
type CompletedHandler = AsyncOperationWithProgressCompletedHandler<T, P>;
fn set_completed<F: Fn() + Send + 'static>(&self, handler: F) -> Result<()> {
self.SetCompleted(&AsyncOperationWithProgressCompletedHandler::new(
move |_, _| {
handler();
Ok(())
},
))
}
fn invoke_completed(&self, handler: &Self::CompletedHandler, status: AsyncStatus) {
_ = handler.Invoke(self, status);
}
fn get_results(&self) -> Result<Self::Output> {
self.GetResults()
}
}
impl IntoFuture for IAsyncAction {
type Output = Result<()>;
type IntoFuture = AsyncFuture<Self>;
fn into_future(self) -> Self::IntoFuture {
AsyncFuture::new(self)
}
}
impl<T: RuntimeType> IntoFuture for IAsyncOperation<T> {
type Output = Result<T>;
type IntoFuture = AsyncFuture<Self>;
fn into_future(self) -> Self::IntoFuture {
AsyncFuture::new(self)
}
}
impl<P: RuntimeType> IntoFuture for IAsyncActionWithProgress<P> {
type Output = Result<()>;
type IntoFuture = AsyncFuture<Self>;
fn into_future(self) -> Self::IntoFuture {
AsyncFuture::new(self)
}
}
impl<T: RuntimeType, P: RuntimeType> IntoFuture for IAsyncOperationWithProgress<T, P> {
type Output = Result<T>;
type IntoFuture = AsyncFuture<Self>;
fn into_future(self) -> Self::IntoFuture {
AsyncFuture::new(self)
}
}