XCB provides functions xcb_{wait,poll}_for_{reply,event}
, but not xcb_{wait,poll}_for_reply_or_event
, which would be useful in the following scenario:
- Send a batch of requests.
- Wait for replies. While waiting, handle incoming events.
- When the replies finally come in, handle the replies.
To implement steps 2 and 3, we could poll
the the underlying socket, as follows:
- Check for queued replies with
xcb_poll_for_reply
. - Check for queued events with
xcb_poll_for_event
. poll
the underlying socket.- When
poll
indicates a read is possible, callxcb_poll_for_reply
and/orxcb_poll_for_event
and process the new data.
However, this seems to have a race condition. If a reply (but not an event) arrives between steps 1 and 2, it will get queued in XCB's internal data structures in step 2. Then we will end up blocking in poll
even though there is data available to process. (Of course, a similar issue occurs if steps 1 and 2 are swapped.)
So, is there any efficient way to wait/poll for replies or events without this deficiency?
CodePudding user response:
The problem can be solved by poll
ing the underlying socket as described in the question, but with xcb_poll_for_event
in step 2 replaced by xcb_poll_for_queued_event
. (This might still be broken in multithreaded scenarios.)
Alternatively, we can avoid needing to poll
the socket by sending an unchecked dummy request that is guaranteed to fail, as follows:
- Send a batch of requests.
- Send an unchecked dummy request that will fail (e.g., MapWindow with an invalid window argument).
- Repeatedly call
xcb_wait_for_event
and handle incoming events while waiting for replies. - Eventually,
xcb_wait_for_event
will return an error. If the sequence number in the error matches the sequence number of the dummy request, then ignore the error and continue to the next step; all replies must have arrived. Otherwise, the error is for a genuine request and should be handled appropriately. - Read in all replies with
xcb_poll_for_reply
or the appropriate generated reply functions.
The first approach is more efficient, but the second approach might lead to simpler code.