[Xcb] [PATCH libX11 3/3] Avoid excessive reads and waiting of events in _XReply.
Rami Ylimäki
rami.ylimaki at vincit.fi
Thu Oct 7 08:43:21 PDT 2010
Previously Xlib executed a vain non-blocking read in XCB whenever
checking for events to handle.
Also Xlib prevented reply handling from advancing if there were no
events and other threads were waiting for events.
Signed-off-by: Rami Ylimäki <rami.ylimaki at vincit.fi>
---
src/xcb_io.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 65 insertions(+), 5 deletions(-)
diff --git a/src/xcb_io.c b/src/xcb_io.c
index 7e685de..2b31480 100644
--- a/src/xcb_io.c
+++ b/src/xcb_io.c
@@ -227,6 +227,64 @@ static xcb_generic_reply_t *poll_for_event(Display *dpy)
return NULL;
}
+/**
+ * Check if we have read events from XCB or whether XCB has some
+ * events in its buffers.
+ *
+ * @param[in]: dpy Connection to X server.
+ *
+ * @param[out]: header Header that is filled with contens of next
+ * available event. If there are no events, header
+ * contents are not modified.
+ *
+ * @return Zero if there are no events available, non-zero otherwise.
+ */
+static Bool peek_for_event(Display *dpy, xcb_generic_event_t *header)
+{
+ require_socket(dpy);
+
+ /* Check if we have already read an event from XCB. */
+ if (dpy->xcb->next_event)
+ {
+ *header = *dpy->xcb->next_event;
+ return True;
+ }
+
+ /* Check if XCB has any events in its buffers. */
+ return xcb_peek_for_event(dpy->xcb->connection, header);
+}
+
+/**
+ * Check if there are events available that should be handled before
+ * the reply to a given request is handled.
+ *
+ * @param[in]: dpy Connection to X server.
+ *
+ * @param[in]: request_sequence Sequence number for a request. The
+ * reply to this request should have been
+ * received from XCB before this function
+ * is called.
+ *
+ * @return Zero if reply to a request can be handled immediately,
+ * non-zero otherwise.
+ */
+static Bool events_exist(Display *dpy, unsigned long request_sequence)
+{
+ xcb_generic_event_t header;
+ /* Check if there are events that should be processed before the
+ * reply to given request. */
+ if (peek_for_event(dpy, &header))
+ {
+ unsigned long header_sequence = dpy->last_request_read;
+ widen(&header_sequence, header.full_sequence);
+ /* If there are no events, or the events came after the
+ * request reply, we don't have to worry about them. */
+ return XLIB_SEQUENCE_COMPARE(header_sequence, <=, request_sequence);
+ }
+
+ return False;
+}
+
static xcb_generic_reply_t *poll_for_response(Display *dpy)
{
void *response;
@@ -541,18 +599,20 @@ Status _XReply(Display *dpy, xReply *rep, int extra, Bool discard)
if(dpy->xcb->event_owner == XlibOwnsEventQueue)
{
xcb_generic_reply_t *event;
+ Bool early_events_exist = events_exist(dpy, req->sequence);
/* If some thread is already waiting for events,
* it will get the first one. That thread must
* process that event before we can continue. */
- /* FIXME: That event might be after this reply,
- * and might never even come--or there might be
- * multiple threads trying to get events. */
- while(dpy->xcb->event_waiter)
+ while(early_events_exist && dpy->xcb->event_waiter)
{ /* need braces around ConditionWait */
ConditionWait(dpy, dpy->xcb->event_notify);
+ early_events_exist = events_exist(dpy, req->sequence);
}
- while((event = poll_for_event(dpy)))
+ while(early_events_exist && (event = poll_for_event(dpy)))
+ {
handle_response(dpy, event, True);
+ early_events_exist = events_exist(dpy, req->sequence);
+ }
}
req->reply_waiter = 0;
--
1.6.3.3
More information about the Xcb
mailing list