1use super::Stats;
2use alloc::sync::Arc;
3use core::future::Future;
4use core::mem::ManuallyDrop;
5use core::pin::Pin;
6use core::task::{Context, Poll, RawWaker, RawWakerVTable, Waker};
7use core::sync::atomic::{AtomicU16, Ordering::Relaxed};
8
9pub struct Wookie<F> {
32 wakey: Arc<Wakey>,
33 ptr: *const Wakey,
34 future: F,
35}
36
37
38impl<F: Future> Wookie<F> {
39
40 #[inline(always)]
43 pub fn new(future: F) -> Wookie<F> {
44 let ptr = Arc::into_raw(Arc::new(Wakey::default()));
45 let wakey = unsafe { Arc::from_raw(ptr) };
46 Wookie { wakey, ptr, future }
47 }
48
49 #[inline(always)]
52 pub fn woken(self: &mut Pin<&mut Self>) -> u16 {
53 self.as_mut().project().wakey.woken.load(Relaxed)
54 }
55
56 #[inline(always)]
59 pub fn cloned(self: &mut Pin<&mut Self>) -> u16 {
60 self.as_mut().project().wakey.cloned.load(Relaxed)
61 }
62
63 #[inline(always)]
67 pub fn dropped(self: &mut Pin<&mut Self>) -> u16 {
68 self.as_mut().project().wakey.dropped.load(Relaxed)
69 }
70
71 #[inline(always)]
73 pub fn stats(self: &mut Pin<&mut Self>) -> Stats {
74 let wakey = self.as_mut().project().wakey.as_ref();
75 Stats {
76 cloned: wakey.cloned.load(Relaxed),
77 dropped: wakey.dropped.load(Relaxed),
78 woken: wakey.woken.load(Relaxed),
79 }
80 }
81 #[inline(always)]
85 pub fn live(self: &mut Pin<&mut Self>) -> u16 {
86 let wakey = self.as_mut().project().wakey.as_ref();
87 wakey.cloned.load(Relaxed) - wakey.dropped.load(Relaxed)
88 }
89
90 #[inline(always)]
101 pub fn poll(
102 self: &mut Pin<&mut Self>
103 ) -> Poll<<F as Future>::Output> {
104 let this = self.as_mut().project();
105 let waker = ManuallyDrop::new(this.waker());
106 let future = unsafe { Pin::new_unchecked(&mut this.future) };
107 let mut ctx = Context::from_waker(&waker);
108 Future::poll(future, &mut ctx)
109 }
110
111 #[inline(always)]
123 pub fn poll_while_woken(
124 self: &mut Pin<&mut Self>
125 ) -> Poll<<F as Future>::Output> {
126 let mut woken = self.woken();
127 loop {
128 if let Poll::Ready(r) = self.poll() { return Poll::Ready(r); }
129 let w = self.woken();
130 if w == woken { return Poll::Pending; }
131 woken = w;
132 }
133 }
134
135 #[inline(always)]
136 fn waker(&self) -> Waker {
137 let raw = wookie_rawwaker(self.ptr);
141 unsafe { Waker::from_raw(raw) }
142 }
143
144 #[inline(always)]
145 fn project(self: Pin<&mut Self>) -> &mut Self {
146 unsafe { Pin::into_inner_unchecked(self) }
147 }
148
149}
150
151
152#[macro_export]
176macro_rules! wookie {
177 ($name:ident) => {
178 let mut $name = unsafe { $crate::Wookie::new($name) };
179 #[allow(unused_mut)]
180 let mut $name = unsafe { core::pin::Pin::new_unchecked(&mut $name) };
181 };
182 ($name:ident : $future:expr) => {
183 let mut $name = unsafe { $crate::Wookie::new($future) };
184 #[allow(unused_mut)]
185 let mut $name = unsafe { core::pin::Pin::new_unchecked(&mut $name) };
186 }
187}
188
189#[derive(Default)]
190struct Wakey {
191 cloned: AtomicU16,
192 dropped: AtomicU16,
193 woken: AtomicU16,
194}
195
196impl Wakey {
197 fn bump_cloned(&self) -> u16 { self.cloned.fetch_add(1, Relaxed) }
198 fn bump_woken(&self) -> u16 { self.woken.fetch_add(1, Relaxed) }
199 fn bump_dropped(&self) -> u16 { self.dropped.fetch_add(1, Relaxed) }
200}
201
202fn wookie_rawwaker(wakey: *const Wakey) -> RawWaker {
203 fn do_clone(data: *const ()) -> RawWaker {
204 let wakey = data as *const Wakey;
205 unsafe { &*wakey }.bump_cloned();
206 unsafe { Arc::increment_strong_count(wakey) };
207 wookie_rawwaker(wakey)
208 }
209
210 fn do_wake(data: *const ()) {
211 let wakey: Arc<Wakey> = unsafe { Arc::from_raw(data as *const Wakey) };
212 wakey.bump_woken();
213 wakey.bump_dropped();
214 }
215
216 fn do_wake_by_ref(data: *const ()) {
217 let arc = unsafe { Arc::from_raw(data as *const Wakey) };
218 let wakey = ManuallyDrop::new(arc);
219 wakey.bump_woken();
220 }
221
222 fn do_drop(data: *const ()) {
223 let wakey: Arc<Wakey> = unsafe { Arc::from_raw(data as *const Wakey) };
224 wakey.bump_dropped();
225 }
226
227 RawWaker::new(
228 wakey as *const (),
229 &RawWakerVTable::new(do_clone, do_wake, do_wake_by_ref, do_drop)
230 )
231}
232