diff options
author | Keith Packard <keithp@keithp.com> | 2008-10-11 21:10:23 -0700 |
---|---|---|
committer | Jamey Sharp <jamey@minilop.net> | 2008-11-04 08:54:01 -0800 |
commit | bedfe68259037c5564fe52758c92b9c97729640a (patch) | |
tree | ba96e1da207ca3a58144a760217ab6a8d081599c | |
parent | cc19618d2eb3ed92a0b574aee26a7da8b4aed5d2 (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.h | 7 | ||||
-rw-r--r-- | src/xcb_disp.c | 2 | ||||
-rw-r--r-- | src/xcb_io.c | 18 |
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) |