rquickjs_core/runtime/schedular/
vtable.rs

1use std::{
2    future::Future,
3    mem::ManuallyDrop,
4    pin::Pin,
5    ptr::NonNull,
6    sync::Arc,
7    task::{Context, Poll},
8};
9
10use super::Task;
11
12#[derive(Debug, Clone)]
13pub(crate) struct VTable {
14    pub(crate) task_drive: unsafe fn(NonNull<Task<()>>, cx: &mut Context) -> Poll<()>,
15    pub(crate) task_decr: unsafe fn(NonNull<Task<()>>),
16    pub(crate) task_incr: unsafe fn(NonNull<Task<()>>),
17    pub(crate) task_drop: unsafe fn(NonNull<Task<()>>),
18}
19
20impl VTable {
21    pub const fn get<F: Future<Output = ()>>() -> &'static VTable {
22        trait HasVTable {
23            const V_TABLE: VTable;
24        }
25
26        impl<F: Future<Output = ()>> HasVTable for F {
27            const V_TABLE: VTable = VTable {
28                task_decr: VTable::decr::<F>,
29                task_drive: VTable::drive::<F>,
30                task_incr: VTable::incr::<F>,
31                task_drop: VTable::drop::<F>,
32            };
33        }
34
35        &<F as HasVTable>::V_TABLE
36    }
37
38    unsafe fn decr<F: Future<Output = ()>>(ptr: NonNull<Task<()>>) {
39        Arc::decrement_strong_count(ptr.cast::<Task<F>>().as_ptr())
40    }
41
42    unsafe fn incr<F: Future<Output = ()>>(ptr: NonNull<Task<()>>) {
43        Arc::increment_strong_count(ptr.cast::<Task<F>>().as_ptr())
44    }
45
46    unsafe fn drive<F: Future<Output = ()>>(ptr: NonNull<Task<()>>, cx: &mut Context) -> Poll<()> {
47        let ptr = ptr.cast::<Task<F>>();
48        Pin::new_unchecked(&mut *(*ptr.as_ref().future.get())).poll(cx)
49    }
50
51    unsafe fn drop<F: Future<Output = ()>>(ptr: NonNull<Task<()>>) {
52        let ptr = ptr.cast::<Task<F>>();
53        unsafe { ManuallyDrop::drop(&mut (*ptr.as_ref().future.get())) }
54    }
55}