use std::{
future::Future,
pin::Pin,
sync::{
atomic::{AtomicUsize, Ordering},
Arc, Mutex, Weak,
},
task::{RawWaker, RawWakerVTable, Waker},
};
use crate::{spawner::Spawner, task::manager::TaskManager};
static TASK_TAG_NUM: AtomicUsize = AtomicUsize::new(0);
#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)]
pub struct TaskTag(usize);
pub struct Task {
pub future: Mutex<Pin<Box<dyn Future<Output = ()> + Send + 'static>>>, pub spawner: Spawner, pub task_tag: TaskTag, pub manager: Weak<TaskManager>, }
impl Task {
const WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new(clone, wake, wake_by_ref, drop);
pub fn waker(self: Arc<Self>) -> Waker {
let opaque_ptr = Arc::into_raw(self) as *const ();
let vtable = &Self::WAKER_VTABLE;
unsafe { Waker::from_raw(RawWaker::new(opaque_ptr, vtable)) }
}
pub fn generate_tag() -> TaskTag {
TaskTag(TASK_TAG_NUM.fetch_add(1, Ordering::Relaxed))
}
}
fn clone(ptr: *const ()) -> RawWaker {
let original: Arc<Task> = unsafe { Arc::from_raw(ptr as _) };
let cloned = original.clone();
std::mem::forget(original);
std::mem::forget(cloned);
RawWaker::new(ptr, &Task::WAKER_VTABLE)
}
fn drop(ptr: *const ()) {
let _: Arc<Task> = unsafe { Arc::from_raw(ptr as _) };
}
fn wake(ptr: *const ()) {
let arc: Arc<Task> = unsafe { Arc::from_raw(ptr as _) };
let tm = arc.manager.upgrade().unwrap();
tm.register_or_execute_task(arc);
}
fn wake_by_ref(ptr: *const ()) {
let arc: Arc<Task> = unsafe { Arc::from_raw(ptr as _) };
let tm = arc.manager.upgrade().unwrap();
tm.register_or_execute_task(Arc::clone(&arc));
std::mem::forget(arc);
}