use super::application::{ApplicationHandle, HasAppHandle};
use std::boxed::Box;
use std::future::Future;
use std::mem;
use std::panic;
use std::pin::Pin;
use std::rc::Rc;
use std::sync::Arc;
use std::task::{
Context,
Poll,
Waker
};
use std::panic::{AssertUnwindSafe, catch_unwind};
use browser_window_core::application::*;
struct DelegateData<'a,'b,H,R> {
handle: H,
result: &'a mut Option<Result<R, DelegateError>>,
func: Box<dyn FnOnce( H ) -> R + Send + 'b>,
waker: Waker
}
struct DelegateFutureData<'a,'b,R> where R: Send {
inner: &'b mut DelegateFutureInner<'a,R>,
waker: Waker
}
#[derive(Debug)]
pub enum DelegateError {
RuntimeNotAvailable,
ClosurePanicked
}
pub struct DelegateFuture<'a,H,R> where
R: Send
{
handle: H,
func: Option<Box<dyn FnOnce( H ) -> R + Send + 'a>>,
result: Option<Result<R, DelegateError>>,
started: bool
}
impl<'a,H,R> Unpin for DelegateFuture<'a,H,R> where R: Send {}
unsafe impl<'a,H,R> Send for DelegateFuture<'a,H,R> where R: Send {}
pub struct DelegateFutureFuture<'a,R> where
R: Send
{
app_handle: ApplicationHandle,
inner: DelegateFutureInner<'a,R>,
started: bool
}
unsafe impl<'a,R> Send for DelegateFutureFuture<'a,R> where R: Send {}
impl<'a,R> Unpin for DelegateFutureFuture<'a,R> where R: Send {}
struct DelegateFutureInner<'a,R> where R: Send {
result: Option<Result<R, DelegateError>>,
future: Pin<Box<dyn Future<Output=R> + 'a>>
}
unsafe impl<'a,R> Send for DelegateFutureInner<'a,R> where R: Send {}
impl<'a,H,R> DelegateFuture<'a,H,R> where R: Send {
pub(in super) fn new<F>( handle: H, func: F ) -> Self where
F: FnOnce( H ) -> R + Send + 'a,
R: Send
{
Self {
handle,
func: Some( Box::new( func ) ),
result: None,
started: false
}
}
}
#[cfg(feature = "threadsafe")]
impl<'a,H,R> Future for DelegateFuture<'a,H,R> where
H: HasAppHandle + Clone + 'static,
R: Send + 'static
{
type Output = Result<R, DelegateError>;
fn poll( mut self: Pin<&mut Self>, cx: &mut Context ) -> Poll<Self::Output> {
if !self.started {
self.started = true;
let app_inner = self.handle.app_handle().inner;
let mut func = None;
mem::swap( &mut self.func, &mut func );
let data = DelegateData {
handle: self.handle.clone(),
func: func.unwrap(),
result: &mut self.result,
waker: cx.waker().clone()
};
let succeeded = {
let data_ptr = Box::into_raw( Box::new( data ) );
app_inner.dispatch( delegate_handler::<H,R>, data_ptr as _ )
};
if !succeeded {
return Poll::Ready( Err( DelegateError::RuntimeNotAvailable ) );
}
Poll::Pending
}
else {
if self.result.is_none() {
return Poll::Pending;
}
let mut temp: Option<Result<R, DelegateError>> = None;
mem::swap( &mut self.result, &mut temp );
Poll::Ready( temp.unwrap() )
}
}
}
#[cfg(feature = "threadsafe")]
impl<'a,R> DelegateFutureFuture<'a,R> where R: Send {
pub(in super) fn new( app_handle: ApplicationHandle, future: impl Future<Output=R> + 'a ) -> Self {
Self {
app_handle,
inner: DelegateFutureInner {
result: None,
future: Box::pin( future )
},
started: false
}
}
}
#[cfg(feature = "threadsafe")]
impl<'a,R> Future for DelegateFutureFuture<'a,R> where R: Send {
type Output = Result<R, DelegateError>;
fn poll( mut self: Pin<&mut Self>, ctx: &mut Context ) -> Poll<Self::Output> {
if !self.started {
self.started = true;
let app_inner = self.app_handle.inner;
let succeeded = unsafe {
let data_ptr = Box::into_raw(Box::new(DelegateFutureData {
inner: &mut self.inner,
waker: ctx.waker().clone(),
}));
app_inner.dispatch( delegate_async_handler::<R>, data_ptr as _ )
};
if !succeeded {
return Poll::Ready(Err(DelegateError::RuntimeNotAvailable));
}
Poll::Pending
}
else {
let mut temp: Option<Result<R, DelegateError>> = None;
mem::swap( &mut self.inner.result, &mut temp );
Poll::Ready( temp.unwrap() )
}
}
}
unsafe fn delegate_handler<H,R>( app: ApplicationImpl, _data: *mut () ) where
H: Clone + 'static,
R: 'static
{
let data_ptr = _data as *mut DelegateData<'static,'static,H,R>;
let data = Box::from_raw( data_ptr ); match *data {
DelegateData{ handle, func, result, waker } => {
match catch_unwind(AssertUnwindSafe(|| {
*result = Some( Ok( func( handle ) ) );
waker.clone().wake();
})) {
Ok(()) => {},
Err( _ ) => {
*result = Some(Err(DelegateError::ClosurePanicked));
waker.wake();
app.exit( -1 );
}
}
}
}
}
#[cfg(feature = "threadsafe")]
unsafe fn delegate_async_handler<R>( app: ApplicationImpl, _data: *mut () ) where R: Send {
let data_ptr = _data as *mut DelegateFutureData<R>;
let data = Box::from_raw( data_ptr ); match *data {
DelegateFutureData{ inner, waker } => {
match panic::catch_unwind(AssertUnwindSafe(|| {
let mut ctx = Context::from_waker( &waker );
match inner.future.as_mut().poll( &mut ctx ) {
Poll::Pending => {},
Poll::Ready( result) => {
inner.result = Some( Ok( result ) );
waker.clone().wake();
}
}
})) {
Ok(()) => {},
Err( _ ) => {
inner.result = Some(Err(DelegateError::ClosurePanicked));
waker.wake();
app.exit( -1 );
}
}
}
}
}