X-Git-Url: http://git.demorecorder.com/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fxcb_in.c;h=e075a40472f006d62f99c0979db5ebe09068dbdb;hb=5ceeaaa4294201b3f613c07f9ec610c0e5f673c7;hp=a084b3f7047b29ff8d20e9dc2cfd51105ed6dbe4;hpb=ed37b087519ecb9e74412e4df8f8a217ab6d12a9;p=free-sw%2Fxcb%2Flibxcb diff --git a/src/xcb_in.c b/src/xcb_in.c index a084b3f..e075a40 100644 --- a/src/xcb_in.c +++ b/src/xcb_in.c @@ -80,6 +80,17 @@ typedef struct reader_list { struct reader_list *next; } reader_list; +static void remove_finished_readers(reader_list **prev_reader, uint64_t completed) +{ + while(*prev_reader && XCB_SEQUENCE_COMPARE((*prev_reader)->request, <=, completed)) + { + /* If you don't have what you're looking for now, you never + * will. Wake up and leave me alone. */ + pthread_cond_signal((*prev_reader)->data); + *prev_reader = (*prev_reader)->next; + } +} + static int read_packet(xcb_connection_t *c) { xcb_generic_reply_t genrep; @@ -130,6 +141,8 @@ static int read_packet(xcb_connection_t *c) if(genrep.response_type == XCB_ERROR) c->in.request_completed = c->in.request_read; + + remove_finished_readers(&c->in.readers, c->in.request_completed); } if(genrep.response_type == XCB_ERROR || genrep.response_type == XCB_REPLY) @@ -154,7 +167,7 @@ static int read_packet(xcb_connection_t *c) } /* XGE events may have sizes > 32 */ - if (genrep.response_type == XCB_XGE_EVENT) + if ((genrep.response_type & 0x7f) == XCB_XGE_EVENT) eventlength = genrep.length * 4; buf = malloc(length + eventlength + @@ -194,7 +207,6 @@ static int read_packet(xcb_connection_t *c) if( genrep.response_type == XCB_REPLY || (genrep.response_type == XCB_ERROR && pend && (pend->flags & XCB_REQUEST_CHECKED))) { - reader_list *reader; struct reply_list *cur = malloc(sizeof(struct reply_list)); if(!cur) { @@ -206,17 +218,8 @@ static int read_packet(xcb_connection_t *c) cur->next = 0; *c->in.current_reply_tail = cur; c->in.current_reply_tail = &cur->next; - for(reader = c->in.readers; - reader && - XCB_SEQUENCE_COMPARE(reader->request, <=, c->in.request_read); - reader = reader->next) - { - if(reader->request == c->in.request_read) - { - pthread_cond_signal(reader->data); - break; - } - } + if(c->in.readers && c->in.readers->request == c->in.request_read) + pthread_cond_signal(c->in.readers->data); return 1; } @@ -356,6 +359,26 @@ static int poll_for_reply(xcb_connection_t *c, uint64_t request, void **reply, x return 1; } +static void insert_reader(reader_list **prev_reader, reader_list *reader, uint64_t request, pthread_cond_t *cond) +{ + while(*prev_reader && XCB_SEQUENCE_COMPARE((*prev_reader)->request, <=, request)) + prev_reader = &(*prev_reader)->next; + reader->request = request; + reader->data = cond; + reader->next = *prev_reader; + *prev_reader = reader; +} + +static void remove_reader(reader_list **prev_reader, reader_list *reader) +{ + while(*prev_reader && XCB_SEQUENCE_COMPARE((*prev_reader)->request, <=, reader->request)) + if(*prev_reader == reader) + { + *prev_reader = (*prev_reader)->next; + break; + } +} + static void *wait_for_reply(xcb_connection_t *c, uint64_t request, xcb_generic_error_t **e) { void *ret = 0; @@ -365,35 +388,14 @@ static void *wait_for_reply(xcb_connection_t *c, uint64_t request, xcb_generic_e { pthread_cond_t cond = PTHREAD_COND_INITIALIZER; reader_list reader; - reader_list **prev_reader; - - for(prev_reader = &c->in.readers; - *prev_reader && - XCB_SEQUENCE_COMPARE((*prev_reader)->request, <=, request); - prev_reader = &(*prev_reader)->next) - { - /* empty */; - } - reader.request = request; - reader.data = &cond; - reader.next = *prev_reader; - *prev_reader = &reader; + + insert_reader(&c->in.readers, &reader, request, &cond); while(!poll_for_reply(c, request, &ret, e)) if(!_xcb_conn_wait(c, &cond, 0, 0)) break; - for(prev_reader = &c->in.readers; - *prev_reader && - XCB_SEQUENCE_COMPARE((*prev_reader)->request, <=, request); - prev_reader = &(*prev_reader)->next) - { - if(*prev_reader == &reader) - { - *prev_reader = (*prev_reader)->next; - break; - } - } + remove_reader(&c->in.readers, &reader); pthread_cond_destroy(&cond); } @@ -525,7 +527,7 @@ xcb_generic_event_t *xcb_wait_for_event(xcb_connection_t *c) return ret; } -xcb_generic_event_t *xcb_poll_for_event(xcb_connection_t *c) +static xcb_generic_event_t *poll_for_next_event(xcb_connection_t *c, int queued) { xcb_generic_event_t *ret = 0; if(!c->has_error) @@ -533,13 +535,23 @@ xcb_generic_event_t *xcb_poll_for_event(xcb_connection_t *c) pthread_mutex_lock(&c->iolock); /* FIXME: follow X meets Z architecture changes. */ ret = get_event(c); - if(!ret && _xcb_in_read(c)) /* _xcb_in_read shuts down the connection on error */ + if(!ret && !queued && c->in.reading == 0 && _xcb_in_read(c)) /* _xcb_in_read shuts down the connection on error */ ret = get_event(c); pthread_mutex_unlock(&c->iolock); } return ret; } +xcb_generic_event_t *xcb_poll_for_event(xcb_connection_t *c) +{ + return poll_for_next_event(c, 0); +} + +xcb_generic_event_t *xcb_poll_for_queued_event(xcb_connection_t *c) +{ + return poll_for_next_event(c, 1); +} + xcb_generic_error_t *xcb_request_check(xcb_connection_t *c, xcb_void_cookie_t cookie) { uint64_t request;