rquickjs_core/runtime/schedular/
vtable.rs1use 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}