wip
1//! Any interaction between an executor/reactor intended for task::Future
2//! with an executor/reactor intended for bcsc::Future is strictly unsound.
3
4use std::{
5 hint::unreachable_unchecked,
6 mem::ManuallyDrop,
7 pin::Pin,
8 ptr::NonNull,
9 task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
10};
11
12use futures_core::Wake;
13use lifetime_guard::{atomic_guard::AtomicValueGuard, guard::ValueGuard};
14
15pub type WakePtr = Option<NonNull<dyn Wake>>;
16pub type LocalWaker = ValueGuard<WakePtr>;
17pub type AtomicWaker = AtomicValueGuard<WakePtr>;
18
19static EVIL_VTABLE: RawWakerVTable = unsafe {
20 RawWakerVTable::new(
21 |_| unreachable_unchecked(),
22 |_| unreachable_unchecked(),
23 |_| unreachable_unchecked(),
24 |_| unreachable_unchecked(),
25 )
26};
27
28/// Coerces a pinned `ValueGuard` reference to a `Waker` for use in
29/// `core::future::Future`
30///
31/// Any usage or storage of the resulting `Waker` is undefined behavior.
32pub unsafe fn guard_to_waker(guard: Pin<&LocalWaker>) -> ManuallyDrop<Waker> {
33 ManuallyDrop::new(unsafe {
34 Waker::from_raw(RawWaker::new(
35 guard.get_ref() as *const ValueGuard<WakePtr> as *const (),
36 &EVIL_VTABLE,
37 ))
38 })
39}
40
41pub unsafe fn atomic_guard_to_waker(
42 guard: Pin<&AtomicWaker>,
43) -> ManuallyDrop<Waker> {
44 ManuallyDrop::new(unsafe {
45 Waker::from_raw(RawWaker::new(
46 guard.get_ref() as *const AtomicValueGuard<WakePtr> as *const (),
47 &EVIL_VTABLE,
48 ))
49 })
50}
51
52/// Coerces a `Waker` into a pinned `AtomicValueGuard` reference.
53///
54/// This should only be used to undo the work of `guard_to_waker`.
55pub unsafe fn waker_to_guard<'a>(waker: &Waker) -> Pin<&LocalWaker> {
56 unsafe {
57 Pin::new_unchecked(&*(waker.data() as *const ValueGuard<WakePtr>))
58 }
59}
60
61pub unsafe fn waker_to_atomic_guard<'a>(waker: &Waker) -> Pin<&AtomicWaker> {
62 unsafe {
63 Pin::new_unchecked(&*(waker.data() as *const AtomicValueGuard<WakePtr>))
64 }
65}
66
67pub unsafe fn std_future_to_bespoke<F: core::future::Future>(
68 future: F,
69) -> impl futures_core::Future<LocalWaker, Output = F::Output> {
70 NormalFutureWrapper(future)
71}
72
73pub unsafe fn bespoke_future_to_std<F: futures_core::Future<LocalWaker>>(
74 future: F,
75) -> impl core::future::Future<Output = F::Output> {
76 BespokeFutureWrapper(future)
77}
78
79/// wraps `core::future::Future` in impl of `bcsc:Future`
80#[repr(transparent)]
81pub struct NormalFutureWrapper<F: core::future::Future>(F);
82
83impl<F: core::future::Future> futures_core::Future<LocalWaker>
84 for NormalFutureWrapper<F>
85{
86 type Output = F::Output;
87
88 fn poll(
89 self: Pin<&mut Self>,
90 waker: Pin<&LocalWaker>,
91 ) -> Poll<Self::Output> {
92 unsafe {
93 self.map_unchecked_mut(|this| &mut this.0)
94 .poll(&mut Context::from_waker(&guard_to_waker(waker)))
95 }
96 }
97}
98
99/// wraps custom `bcsc::Future` in impl of `core::future::Future`
100#[repr(transparent)]
101pub struct BespokeFutureWrapper<F>(F)
102where
103 F: futures_core::Future<LocalWaker>;
104
105impl<F> core::future::Future for BespokeFutureWrapper<F>
106where
107 F: futures_core::Future<LocalWaker>,
108{
109 type Output = F::Output;
110
111 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
112 unsafe {
113 self.map_unchecked_mut(|this| &mut this.0)
114 .poll(waker_to_guard(cx.waker()))
115 }
116 }
117}
118
119#[cfg(test)]
120mod test {
121 use std::pin;
122
123 use super::*;
124 use futures_core::Wake;
125
126 #[derive(Debug)]
127 struct DummyWake;
128 impl Wake for DummyWake {
129 fn wake(&self) {}
130 }
131
132 #[test]
133 fn waker_conversion() {
134 let dummy = DummyWake;
135 let guard = pin::pin!(ValueGuard::new(NonNull::new(
136 &dummy as *const dyn Wake as *mut dyn Wake
137 )));
138 let waker = unsafe { guard_to_waker(guard.as_ref()) };
139 let guard = unsafe { waker_to_guard(&waker) };
140 assert_eq!(
141 guard.get().unwrap().as_ptr() as *const () as usize,
142 &dummy as *const _ as *const () as usize
143 );
144 }
145}