use super::*;
#[derive(Default)]
struct OutcomeQueue {
items: parking_lot::Mutex<VecDeque<SessionOutcome>>,
arrival: parking_lot::Condvar,
}
#[derive(Clone, Default)]
pub struct OutcomeSink {
queue: Arc<OutcomeQueue>,
}
impl OutcomeSink {
pub fn push(&self, outcome: SessionOutcome) {
self.queue.items.lock().push_back(outcome);
self.queue.arrival.notify_all();
}
}
#[derive(Clone, Default)]
pub struct OutcomeFeed {
queue: Arc<OutcomeQueue>,
}
impl OutcomeFeed {
pub fn channel() -> (OutcomeSink, Self) {
let queue = Arc::new(OutcomeQueue::default());
(
OutcomeSink {
queue: Arc::clone(&queue),
},
Self { queue },
)
}
pub fn try_recv(&self) -> Option<SessionOutcome> {
self.queue.items.lock().pop_front()
}
pub fn recv_timeout(&self, timeout: Duration) -> Option<SessionOutcome> {
let deadline = Instant::now() + timeout;
let mut items = self.queue.items.lock();
while items.is_empty() {
let left = deadline.saturating_duration_since(Instant::now());
if self.queue.arrival.wait_for(&mut items, left).timed_out() && items.is_empty() {
return None;
}
}
items.pop_front()
}
}