monoio/task/
mod.rs

1//! Task impl
2// Heavily borrowed from tokio.
3// Copyright (c) 2021 Tokio Contributors, licensed under the MIT license.
4
5mod utils;
6pub(crate) mod waker_fn;
7
8mod core;
9use self::core::{Cell, Header};
10
11mod harness;
12use self::harness::Harness;
13
14mod join;
15#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411
16pub use self::join::JoinHandle;
17
18mod raw;
19use self::raw::RawTask;
20
21mod state;
22
23mod waker;
24
25use std::{future::Future, marker::PhantomData, ptr::NonNull};
26
27/// An owned handle to the task, tracked by ref count, not sendable
28#[repr(transparent)]
29pub(crate) struct Task<S: 'static> {
30    raw: RawTask,
31    _p: PhantomData<S>,
32}
33
34impl<S: 'static> Task<S> {
35    unsafe fn from_raw(ptr: NonNull<Header>) -> Task<S> {
36        Task {
37            raw: RawTask::from_raw(ptr),
38            _p: PhantomData,
39        }
40    }
41
42    fn header(&self) -> &Header {
43        self.raw.header()
44    }
45
46    pub(crate) fn run(self) {
47        self.raw.poll();
48    }
49
50    #[cfg(feature = "sync")]
51    pub(crate) unsafe fn finish(&mut self, val_slot: *mut ()) {
52        self.raw.finish(val_slot);
53    }
54}
55
56impl<S: 'static> Drop for Task<S> {
57    fn drop(&mut self) {
58        // Decrement the ref count
59        if self.header().state.ref_dec() {
60            // Deallocate if this is the final ref count
61            self.raw.dealloc();
62        }
63    }
64}
65
66pub(crate) trait Schedule: Sized + 'static {
67    /// Schedule the task
68    fn schedule(&self, task: Task<Self>);
69    /// Schedule the task to run in the near future, yielding the thread to
70    /// other tasks.
71    fn yield_now(&self, task: Task<Self>) {
72        self.schedule(task);
73    }
74}
75
76pub(crate) fn new_task<T, S>(
77    owner_id: usize,
78    task: T,
79    scheduler: S,
80) -> (Task<S>, JoinHandle<T::Output>)
81where
82    S: Schedule,
83    T: Future + 'static,
84    T::Output: 'static,
85{
86    unsafe { new_task_holding(owner_id, task, scheduler) }
87}
88
89pub(crate) unsafe fn new_task_holding<T, S>(
90    owner_id: usize,
91    task: T,
92    scheduler: S,
93) -> (Task<S>, JoinHandle<T::Output>)
94where
95    S: Schedule,
96    T: Future,
97{
98    let raw = RawTask::new::<T, S>(owner_id, task, scheduler);
99    let task = Task {
100        raw,
101        _p: PhantomData,
102    };
103    let join = JoinHandle::new(raw);
104
105    (task, join)
106}