summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2008-10-11 21:10:23 -0700
committerJamey Sharp <jamey@minilop.net>2008-11-04 08:54:01 -0800
commitbedfe68259037c5564fe52758c92b9c97729640a (patch)
treeba96e1da207ca3a58144a760217ab6a8d081599c
parentcc19618d2eb3ed92a0b574aee26a7da8b4aed5d2 (diff)
Permit only one Xlib thread to block waiting for events
As Xlib queues events internally, we must prevent multiple Xlib threads from entering XCB to wait for an event in case the queued event is to be delivered to the thread which didn't manage to read it. In other words, let only one Xlib thread into xcb_wait_for_event at a time. Jamey Sharp looked over my shoulder while making this fix and, while hating my whitespace conventions, appears happy enough with the actual code. Signed-off-by: Keith Packard <keithp@keithp.com>
-rw-r--r--src/Xxcbint.h7
-rw-r--r--src/xcb_disp.c2
-rw-r--r--src/xcb_io.c18
3 files changed, 23 insertions, 4 deletions
diff --git a/src/Xxcbint.h b/src/Xxcbint.h
index 1b3137b9..f6afa183 100644
--- a/src/Xxcbint.h
+++ b/src/Xxcbint.h
@@ -8,6 +8,7 @@
#include <stdint.h>
#include <X11/Xlibint.h>
#include <X11/Xlib-xcb.h>
+#include "locking.h"
#define XLIB_SEQUENCE_COMPARE(a,op,b) (((long) (a) - (long) (b)) op 0)
@@ -29,6 +30,12 @@ typedef struct _X11XCBPrivate {
uint64_t last_flushed;
enum XEventQueueOwner event_owner;
XID next_xid;
+
+ /* handle simultaneous threads waiting for events,
+ * used in wait_or_poll_for_event
+ */
+ xcondition_t event_notify;
+ int event_waiter;
} _X11XCBPrivate;
/* xcb_disp.c */
diff --git a/src/xcb_disp.c b/src/xcb_disp.c
index dfd6803c..628c6545 100644
--- a/src/xcb_disp.c
+++ b/src/xcb_disp.c
@@ -93,6 +93,7 @@ int _XConnectXCB(Display *dpy, _Xconst char *display, char **fullnamep, int *scr
dpy->xcb->pending_requests_tail = &dpy->xcb->pending_requests;
dpy->xcb->next_xid = xcb_generate_id(dpy->xcb->connection);
+ dpy->xcb->event_notify = xcondition_malloc();
return !xcb_connection_has_error(c);
}
@@ -106,5 +107,6 @@ void _XFreeX11XCBStructure(Display *dpy)
dpy->xcb->pending_requests = tmp->next;
free(tmp);
}
+ xcondition_free(dpy->xcb->event_notify);
Xfree(dpy->xcb);
}
diff --git a/src/xcb_io.c b/src/xcb_io.c
index d0abf4c6..de5525bc 100644
--- a/src/xcb_io.c
+++ b/src/xcb_io.c
@@ -125,9 +125,20 @@ static xcb_generic_event_t * wait_or_poll_for_event(Display *dpy, int wait)
xcb_generic_event_t *event;
if(wait)
{
- UnlockDisplay(dpy);
- event = xcb_wait_for_event(c);
- LockDisplay(dpy);
+ if(dpy->xcb->event_waiter)
+ {
+ ConditionWait(dpy, dpy->xcb->event_notify);
+ event = xcb_poll_for_event(c);
+ }
+ else
+ {
+ dpy->xcb->event_waiter = 1;
+ UnlockDisplay(dpy);
+ event = xcb_wait_for_event(c);
+ LockDisplay(dpy);
+ dpy->xcb->event_waiter = 0;
+ ConditionBroadcast(dpy, dpy->xcb->event_notify);
+ }
}
else
event = xcb_poll_for_event(c);
@@ -228,7 +239,6 @@ static void process_responses(Display *dpy, int wait_for_first_event, xcb_generi
_XIOError(dpy);
assert(XLIB_SEQUENCE_COMPARE(dpy->last_request_read, <=, dpy->request));
- assert(!wait_for_first_event);
}
int _XEventsQueued(Display *dpy, int mode)