use std::{
collections::VecDeque,
sync::{Arc, RwLock},
task::Waker,
};
use dioxus_interpreter_js::MutationState;
#[derive(Default, Clone)]
pub(crate) struct WryQueue {
inner: Arc<RwLock<WryQueueInner>>,
}
#[derive(Default)]
pub(crate) struct WryQueueInner {
edit_queue: VecDeque<Vec<u8>>,
edit_responder: Option<wry::RequestAsyncResponder>,
waiting_for_edits_flushed: Vec<Waker>,
edits_in_progress: bool,
mutation_state: MutationState,
}
impl WryQueue {
pub fn handle_request(&self, responder: wry::RequestAsyncResponder) {
let mut myself = self.inner.write().unwrap();
if let Some(bytes) = myself.edit_queue.pop_back() {
responder.respond(wry::http::Response::new(bytes));
} else {
for waker in myself.waiting_for_edits_flushed.drain(..) {
waker.wake();
}
myself.edits_in_progress = false;
myself.edit_responder = Some(responder);
}
}
pub fn with_mutation_state_mut<O: 'static>(
&self,
f: impl FnOnce(&mut MutationState) -> O,
) -> O {
let mut inner = self.inner.write().unwrap();
f(&mut inner.mutation_state)
}
pub(crate) fn send_edits(&self) {
let mut myself = self.inner.write().unwrap();
let serialized_edits = myself.mutation_state.export_memory();
myself.edits_in_progress = true;
if let Some(responder) = myself.edit_responder.take() {
responder.respond(wry::http::Response::new(serialized_edits));
} else {
myself.edit_queue.push_front(serialized_edits);
}
}
fn edits_in_progress(&self) -> bool {
self.inner.read().unwrap().edits_in_progress
}
pub fn poll_edits_flushed(&self, cx: &mut std::task::Context<'_>) -> std::task::Poll<()> {
if self.edits_in_progress() {
let mut myself = self.inner.write().unwrap();
let waker = cx.waker();
myself.waiting_for_edits_flushed.push(waker.clone());
std::task::Poll::Pending
} else {
std::task::Poll::Ready(())
}
}
}