1use std::{
2 cell::{RefCell, UnsafeCell},
3 future::Future,
4 pin::Pin,
5 rc::Rc,
6 sync::mpsc::Sender,
7 task::{Context, Poll},
8};
9
10use crate::waker::from_task;
11
12pub struct Task {
14 future: UnsafeCell<Box<dyn Future<Output = ()>>>,
16 pub(crate) task_queue: Sender<Rc<Task>>,
18}
19
20impl Task {
21 pub(crate) fn new(
23 future: impl Future<Output = ()> + 'static,
24 task_queue: Sender<Rc<Self>>,
25 ) -> Self {
26 Self {
27 future: UnsafeCell::new(Box::new(future)),
28 task_queue,
29 }
30 }
31
32 pub(crate) fn poll(self: Rc<Self>) -> Poll<()> {
34 let future = unsafe { &mut *self.future.get() }.as_mut();
36 let pin = unsafe { Pin::new_unchecked(future) };
38
39 let task_sender = self.task_queue.clone();
40
41 let waker = from_task(self);
42 let mut context = Context::from_waker(&waker);
43
44 CURRENT_TASK_SENDER.with(|cell| {
45 cell.replace(Some(task_sender));
46 let res = pin.poll(&mut context);
47 cell.replace(None);
48 res
49 })
50 }
51
52 pub fn spawn(future: impl Future<Output = ()> + 'static) {
57 let task_sender = CURRENT_TASK_SENDER.with(|cell| {
58 cell.borrow()
59 .as_ref()
60 .expect("Task::spawn() called from outside an executor")
61 .clone()
62 });
63
64 let task_sender2 = task_sender.clone();
65
66 let task = Self::new(future, task_sender);
67 task_sender2.send(Rc::new(task)).unwrap();
68 }
69}
70
71thread_local! {
72 pub(crate) static CURRENT_TASK_SENDER: RefCell<Option<Sender<Rc<Task>>>> = RefCell::new(None);
74}