Last active
August 1, 2024 09:52
-
-
Save Frando/b24c1c4c7626b1c5e4033e42685cb80a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
struct Item; | |
struct Foo { recv_wakers: VecDeque<GuardedWaker> } | |
impl Foo { | |
fn wake_recv(&mut self) { | |
while let Some(waker) = self.recv_wakers.pop_front() { | |
if waker.wake_if_alive() { | |
break; | |
} | |
} | |
} | |
fn poll_recv(&mut self, cx: &mut Context<'_>) -> PollGuarded<Item> { | |
if self.ready() { | |
PollGuarded::Ready(Item) | |
} else { | |
let (guarded_waker, guard) = GuardedWaker::new(cx.waker().to_owned()); | |
self.wakers.push_back(guarded_waker); | |
Poll::Pending(guard) | |
} | |
} | |
/// Returns a future that may be dropped without concern! | |
fn recv(&mut self) -> RecvFut<'_> { | |
RecvFut { foo: &mut self, guard: None } | |
} | |
} | |
pub struct RecvFut<'a> { | |
foo: &'a mut Foo<>, | |
waker_guard: Option<WakerGuard>, | |
} | |
impl<'a, T> Future for RecvFut<'a, T> { | |
type Output = Option<T>; | |
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { | |
match self.foo.poll_recv(cx) { | |
PollGuarded::Ready(item) => Poll::Ready(item), | |
PollGuarded::Pending(guard) => { | |
self.get_mut().waker_guard = Some(guard); | |
Poll::Pending | |
} | |
} | |
} | |
} | |
enum PollGuarded<T> { | |
Ready(T), | |
Pending(WakerGuard), | |
} | |
#[derive(Debug)] | |
struct GuardedWaker { | |
waker: Waker, | |
guard: Arc<OnceLock<()>>, | |
} | |
impl GuardedWaker { | |
pub fn new(waker: Waker) -> (Self, WakerGuard) { | |
let lock = Arc::new(OnceLock::new()); | |
let guard = WakerGuard(lock.clone()); | |
let waker = Self { waker, guard: lock }; | |
(waker, guard) | |
} | |
pub fn wake_if_alive(self) -> bool { | |
if self.is_alive() { | |
self.wake(); | |
true | |
} else { | |
false | |
} | |
} | |
fn is_alive(&self) -> bool { | |
self.guard.get().is_none() | |
} | |
pub fn wake(self) { | |
self.waker.wake() | |
} | |
} | |
#[derive(Debug)] | |
struct WakerGuard(Arc<OnceLock<()>>); | |
impl Drop for WakerGuard { | |
fn drop(&mut self) { | |
let _ = self.0.set(()); | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment