use std::prelude::v1::*;
use alloc::sync::Arc;
use std::pin::Pin;
use std::task::{Context, Poll};
use async_trait::async_trait;
use futures_task::SpawnError;
use crate::{Future, Timer};
use crate::{Executor, ExecutorPerform};
#[cfg(feature = "exec_async_std")]
pub struct AsyncStdExecutor {
duration: Option<std::time::Duration>
}
#[cfg(feature = "exec_async_std")]
#[async_trait]
impl Executor<async_std::task::JoinHandle<()>> for AsyncStdExecutor {
async fn context() -> Result<Self, SpawnError> where Self: Sized {
Ok(Self { duration: None })
}
async fn set_context(&mut self, _executor: async_std::task::JoinHandle<()>) {
}
async fn enter_context(&self) {
}
async fn get_executor(&self) -> &async_std::task::JoinHandle<()> {
panic!("async-std does not support executor handles - use spawn_in_context instead")
}
fn context_sync() -> Result<Self, SpawnError> where Self: Sized {
Ok(Self { duration: None })
}
fn set_context_sync(&mut self, _executor: async_std::task::JoinHandle<()>) {
}
fn enter_context_sync(&self) {
}
fn get_executor_sync(&self) -> &async_std::task::JoinHandle<()> {
panic!("async-std does not support executor handles - use spawn_in_context_sync instead")
}
}
#[cfg(feature = "exec_async_std")]
#[async_trait]
impl ExecutorPerform<async_std::task::JoinHandle<()>> for AsyncStdExecutor {
async fn spawn_in_context<F>(future: F) -> Result<Arc<dyn crate::Task<F::Output, Output=F::Output>>, SpawnError> where F: Future + Send + 'static, F::Output: Send + 'static {
let handle = async_std::task::spawn(future);
Ok(Arc::new(Task::new(handle)))
}
async fn spawn_from_executor<E, F>(_executor: &E, future: F) -> Result<Arc<dyn crate::Task<F::Output, Output=F::Output>>, SpawnError>
where
E: Executor<async_std::task::JoinHandle<()>>,
F: Future + Send + 'static,
F::Output: Send + 'static
{
let handle = async_std::task::spawn(future);
Ok(Arc::new(Task::new(handle)))
}
async fn block_from_executor<E, F>(_executor: &E, future: F) -> F::Output
where
E: Executor<async_std::task::JoinHandle<()>>,
F: Future + Send + 'static,
F::Output: Send + 'static
{
async_std::task::block_on(future)
}
fn spawn_in_context_sync<F>(future: F) -> Result<Arc<dyn crate::Task<F::Output, Output=F::Output>>, SpawnError> where F: Future + Send + 'static, F::Output: Send + 'static {
let handle = async_std::task::spawn(future);
Ok(Arc::new(Task::new(handle)))
}
fn spawn_from_executor_sync<E, F>(_executor: &E, future: F) -> Result<Arc<dyn crate::Task<F::Output, Output=F::Output>>, SpawnError> where E: Executor<async_std::task::JoinHandle<()>>, F: Future + Send + 'static, F::Output: Send + 'static {
let handle = async_std::task::spawn(future);
Ok(Arc::new(Task::new(handle)))
}
fn block_from_executor_sync<E, F>(_executor: &E, future: F) -> F::Output where E: Executor<async_std::task::JoinHandle<()>>, F: Future + Send + 'static, F::Output: Send + 'static {
async_std::task::block_on(future)
}
}
#[cfg(feature = "exec_async_std")]
#[async_trait]
impl Timer for AsyncStdExecutor {
async fn once(duration_millis: u32) -> Self {
let duration = std::time::Duration::from_millis(u64::from(duration_millis));
Self {
duration: Some(duration)
}
}
async fn interval(duration_millis: u32) -> Self {
let duration = std::time::Duration::from_millis(u64::from(duration_millis));
Self {
duration: Some(duration)
}
}
async fn cancel(&mut self) {
self.duration = None;
}
fn once_sync(duration_millis: u32) -> Self {
let duration = std::time::Duration::from_millis(u64::from(duration_millis));
Self {
duration: Some(duration)
}
}
fn interval_sync(duration_millis: u32) -> Self {
let duration = std::time::Duration::from_millis(u64::from(duration_millis));
Self {
duration: Some(duration)
}
}
fn cancel_sync(&mut self) {
self.duration = None;
}
async fn tick(&mut self) -> u32 {
match self.duration {
None => panic!("Timer has been dropped"),
Some(duration) => {
async_std::task::sleep(duration).await;
u32::try_from(duration.as_millis()).unwrap_or(0)
}
}
}
}
#[cfg(feature = "exec_async_std")]
impl Clone for AsyncStdExecutor {
fn clone(&self) -> Self {
Self { duration: None }
}
}
#[cfg(feature = "exec_async_std")]
pub struct Task<T> {
detached: bool,
handle: async_std::task::JoinHandle<T>
}
#[cfg(feature = "exec_async_std")]
impl<T> Task<T> {
pub const fn new(handle: async_std::task::JoinHandle<T>) -> Self {
Self {
detached: false,
handle
}
}
}
#[cfg(feature = "exec_async_std")]
impl<T> Future for Task<T> {
type Output = T;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let handle = &mut self.get_mut().handle;
Poll::Ready(futures_util::ready!(Pin::new(handle).poll(cx)))
}
}
#[cfg(feature = "exec_async_std")]
#[async_trait]
impl<T: Send + 'static> crate::Task<T> for Task<T> {
async fn output(self) -> T {
self.handle.await
}
fn detach(mut self) {
self.detached = true;
}
fn drop(self) {
if !self.detached { drop(self.handle) }
}
}
#[cfg(all(feature = "hyper_executor", feature = "exec_async_std"))]
impl<F> hyper::rt::Executor<F> for AsyncStdExecutor
where
F: Future + Send + 'static,
F::Output: Send + 'static
{
fn execute(&self, fut: F) {
let _ = Self::spawn_in_context_sync(fut);
}
}