Skip to content

Instantly share code, notes, and snippets.

@Frando
Last active August 1, 2024 09:52
Show Gist options
  • Save Frando/b24c1c4c7626b1c5e4033e42685cb80a to your computer and use it in GitHub Desktop.
Save Frando/b24c1c4c7626b1c5e4033e42685cb80a to your computer and use it in GitHub Desktop.
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