1//! Management of pending errors for the XCB connection.
2//!
3//! We add our own error tracking ontop of what XCB already provides. For this reason, this module
4//! contains a struct for tracking requests that were send and also tracking errors that were
5//! received, but not yet given to the user of this library.
67use std::cmp::Reverse;
8use std::collections::{BinaryHeap, VecDeque};
9use std::sync::Mutex;
1011use super::{Buffer, XCBConnection};
12use x11rb_protocol::SequenceNumber;
1314#[derive(Debug, Default)]
15struct PendingErrorsInner {
16 in_flight: BinaryHeap<Reverse<SequenceNumber>>,
17 pending: VecDeque<(SequenceNumber, Buffer)>,
18}
1920/// A management struct for pending X11 errors
21#[derive(Debug, Default)]
22pub(crate) struct PendingErrors {
23 inner: Mutex<PendingErrorsInner>,
24}
2526impl PendingErrors {
27pub(crate) fn append_error(&self, error: (SequenceNumber, Buffer)) {
28self.inner.lock().unwrap().pending.push_back(error)
29 }
3031pub(crate) fn discard_reply(&self, sequence: SequenceNumber) {
32self.inner.lock().unwrap().in_flight.push(Reverse(sequence));
33 }
3435pub(crate) fn get(&self, conn: &XCBConnection) -> Option<(SequenceNumber, Buffer)> {
36let mut inner = self.inner.lock().unwrap();
3738// Check if we already have an element at hand
39let err = inner.pending.pop_front();
40if err.is_some() {
41return err;
42 }
4344// Check if any of the still in-flight responses got a reply/error
45while let Some(&Reverse(seqno)) = inner.in_flight.peek() {
46let result = match conn.poll_for_reply(seqno) {
47Err(()) => {
48// This request was not answered/errored yet, so later request will not
49 // have answers as well.
50return None;
51 }
52Ok(reply) => reply,
53 };
5455let seqno2 = inner.in_flight.pop();
56assert_eq!(Some(Reverse(seqno)), seqno2);
5758if let Some(result) = result {
59// Is this an error?
60if result[0] == 0 {
61return Some((seqno, result));
62 } else {
63// It's a reply, just ignore it
64}
65 }
66 }
6768None
69}
70}