use std::any::Any; use std::collections::VecDeque; use super::Canceller; use crate::interpreted::ExprInst; pub type SyncResult = (T, Box); pub type SyncOperation = Box SyncResult + Send>; pub type SyncOpResultHandler = Box, Canceller) -> (T, Vec)>; struct SyncQueueItem { cancelled: Canceller, operation: SyncOperation, handler: SyncOpResultHandler, early_cancel: Box (T, Vec)>, } pub enum NextItemReportKind { Free(T), Next { instance: T, cancelled: Canceller, operation: SyncOperation, rest: BusyState, }, Taken, } pub struct NextItemReport { pub kind: NextItemReportKind, pub events: Vec, } pub struct BusyState { handler: SyncOpResultHandler, queue: VecDeque>, seal: Option Vec>>, } impl BusyState { pub fn new( handler: impl FnOnce(T, U, Canceller) -> (T, Vec) + 'static, ) -> Self { BusyState { handler: Box::new(|t, payload, cancel| { let u = *payload .downcast() .expect("mismatched initial handler and operation"); handler(t, u, cancel) }), queue: VecDeque::new(), seal: None, } } /// Add a new operation to the queue. Returns Some if the operation was /// successfully enqueued and None if the queue is already sealed. pub fn enqueue( &mut self, operation: impl FnOnce(T, Canceller) -> (T, U) + Send + 'static, handler: impl FnOnce(T, U, Canceller) -> (T, Vec) + 'static, early_cancel: impl FnOnce(T) -> (T, Vec) + 'static, ) -> Option { if self.seal.is_some() { return None; } let cancelled = Canceller::new(); self.queue.push_back(SyncQueueItem { cancelled: cancelled.clone(), early_cancel: Box::new(early_cancel), operation: Box::new(|t, c| { let (t, r) = operation(t, c); (t, Box::new(r)) }), handler: Box::new(|t, u, c| { let u = u.downcast().expect("mismatched handler and operation"); handler(t, *u, c) }), }); Some(cancelled) } pub fn seal(&mut self, recipient: impl FnOnce(T) -> Vec + 'static) { assert!(self.seal.is_none(), "Already sealed"); self.seal = Some(Box::new(recipient)) } pub fn is_sealed(&self) -> bool { self.seal.is_some() } pub fn rotate( mut self, instance: T, result: U, cancelled: Canceller, ) -> NextItemReport { let (mut instance, mut events) = (self.handler)(instance, Box::new(result), cancelled); let next_item = loop { if let Some(candidate) = self.queue.pop_front() { if candidate.cancelled.is_cancelled() { let ret = (candidate.early_cancel)(instance); instance = ret.0; events.extend(ret.1.into_iter()); } else { break candidate; } } else if let Some(seal) = self.seal.take() { seal(instance); let kind = NextItemReportKind::Taken; return NextItemReport { events, kind }; } else { let kind = NextItemReportKind::Free(instance); return NextItemReport { events, kind }; } }; self.handler = next_item.handler; NextItemReport { events, kind: NextItemReportKind::Next { instance, cancelled: next_item.cancelled, operation: next_item.operation, rest: self, }, } } }