use std::future::Future;
use std::pin::Pin;
use std::sync::atomic::Ordering;
use std::sync::{Arc, Mutex};
use std::task::{Context, Poll, Wake, Waker};
use crate::runitime::Runtime;
type PinFuture = Mutex<Pin<Box<dyn Future<Output = ()> + Send + 'static>>>;
pub(crate) struct Task {
future: PinFuture,
block: bool,
waker: Option<Arc<Waker>>,
}
impl Wake for Task {
fn wake(self: Arc<Self>) {
if self.is_blocking() {
Runtime::get().inner_spawn_blocking(self);
} else {
Runtime::get().inner_spawn(self);
}
}
}
impl Drop for Task {
fn drop(&mut self) {
Runtime::get().size.fetch_sub(1, Ordering::Relaxed);
}
}
impl Task {
pub(crate) fn new(block: bool, future: impl Future<Output = ()> + Send + 'static) -> Arc<Self> {
Runtime::get().size.fetch_add(1, Ordering::Relaxed);
Arc::new(Task {
future: Mutex::new(Box::pin(future)),
block,
waker: None,
})
}
pub fn poll(self: &Arc<Self>) -> Poll<()> {
if let None = self.waker {
let waker = self.waker();
let mut ctx = Context::from_waker(&waker);
self.future.lock().unwrap().as_mut().poll(&mut ctx)
} else {
Poll::Pending
}
}
pub fn waker(self: &Arc<Self>) -> Waker {
self.clone().into()
}
pub fn is_blocking(&self) -> bool {
self.block
}
}