use super::polling::{EventKey, Poller};
use alloc::rc::Rc;
use core::cell::RefCell;
use core::future;
use core::task::Poll;
use core::task::Waker;
#[cfg(not(feature = "std"))]
use hashbrown::HashMap;
#[cfg(feature = "std")]
use std::collections::HashMap;
use wasi::io::poll::Pollable;
#[derive(Debug, Clone)]
pub struct Reactor {
inner: Rc<RefCell<InnerReactor>>,
}
#[derive(Debug)]
struct InnerReactor {
poller: Poller,
wakers: HashMap<EventKey, Waker>,
}
impl Reactor {
pub(crate) fn new() -> Self {
Self {
inner: Rc::new(RefCell::new(InnerReactor {
poller: Poller::new(),
wakers: HashMap::new(),
})),
}
}
pub(crate) fn block_until(&self) {
let mut reactor = self.inner.borrow_mut();
for key in reactor.poller.block_until() {
match reactor.wakers.get(&key) {
Some(waker) => waker.wake_by_ref(),
None => panic!("tried to wake the waker for non-existent `{key:?}`"),
}
}
}
pub async fn wait_for(&self, pollable: Pollable) {
let mut pollable = Some(pollable);
let mut key = None;
future::poll_fn(|cx| {
let mut reactor = self.inner.borrow_mut();
let key = key.get_or_insert_with(|| reactor.poller.insert(pollable.take().unwrap()));
reactor.wakers.insert(*key, cx.waker().clone());
if reactor.poller.get(key).unwrap().ready() {
reactor.poller.remove(*key);
reactor.wakers.remove(key);
Poll::Ready(())
} else {
Poll::Pending
}
})
.await
}
}