diff options
-rw-r--r-- | src/xcb_in.c | 77 | ||||
-rw-r--r-- | src/xcb_list.c | 10 | ||||
-rw-r--r-- | src/xcbint.h | 11 |
3 files changed, 57 insertions, 41 deletions
diff --git a/src/xcb_in.c b/src/xcb_in.c index cdaf558..76990f3 100644 --- a/src/xcb_in.c +++ b/src/xcb_in.c @@ -41,6 +41,11 @@ struct event_list { struct event_list *next; }; +struct reply_list { + void *reply; + struct reply_list *next; +}; + typedef struct pending_reply { unsigned int request; enum workarounds workaround; @@ -99,10 +104,11 @@ static int read_packet(XCBConnection *c) c->in.pending_replies_tail = &c->in.pending_replies; free(oldpend); } - if(!_xcb_queue_is_empty(c->in.current_reply)) + if(c->in.current_reply) { _xcb_map_put(c->in.replies, lastread, c->in.current_reply); - c->in.current_reply = _xcb_queue_new(); + c->in.current_reply = 0; + c->in.current_reply_tail = &c->in.current_reply; } } if(c->in.request_read < lastread) @@ -140,7 +146,13 @@ static int read_packet(XCBConnection *c) if(genrep.response_type == 1 || (genrep.response_type == 0 && pend && (pend->flags & XCB_REQUEST_CHECKED))) { XCBReplyData *reader = _xcb_list_find(c->in.readers, match_reply, &c->in.request_read); - _xcb_queue_enqueue(c->in.current_reply, buf); + struct reply_list *cur = malloc(sizeof(struct reply_list)); + if(!cur) + return 0; + cur->reply = buf; + cur->next = 0; + *c->in.current_reply_tail = cur; + c->in.current_reply_tail = &cur->next; if(reader) pthread_cond_signal(reader->data); return 1; @@ -175,6 +187,17 @@ static XCBGenericEvent *get_event(XCBConnection *c) return ret; } +static void free_reply_list(struct reply_list *head) +{ + while(head) + { + struct reply_list *cur = head; + head = cur->next; + free(cur->reply); + free(cur); + } +} + static int read_block(const int fd, void *buf, const size_t len) { int done = 0; @@ -202,6 +225,7 @@ void *XCBWaitForReply(XCBConnection *c, unsigned int request, XCBGenericError ** { pthread_cond_t cond = PTHREAD_COND_INITIALIZER; XCBReplyData reader; + struct reply_list *head; void *ret = 0; if(e) *e = 0; @@ -222,31 +246,40 @@ void *XCBWaitForReply(XCBConnection *c, unsigned int request, XCBGenericError ** /* If this request has not been read yet, wait for it. */ while(((signed int) (c->in.request_read - request) < 0 || - (c->in.request_read == request && - _xcb_queue_is_empty(c->in.current_reply)))) + (c->in.request_read == request && !c->in.current_reply))) if(!_xcb_conn_wait(c, /*should_write*/ 0, &cond)) goto done; if(c->in.request_read != request) { - _xcb_queue *q = _xcb_map_get(c->in.replies, request); - if(q) + head = _xcb_map_remove(c->in.replies, request); + if(head && head->next) + _xcb_map_put(c->in.replies, request, head->next); + } + else + { + head = c->in.current_reply; + if(head) { - ret = _xcb_queue_dequeue(q); - if(_xcb_queue_is_empty(q)) - _xcb_queue_delete(_xcb_map_remove(c->in.replies, request), free); + c->in.current_reply = head->next; + if(!head->next) + c->in.current_reply_tail = &c->in.current_reply; } } - else - ret = _xcb_queue_dequeue(c->in.current_reply); - if(ret && ((XCBGenericRep *) ret)->response_type == 0) /* X error */ + if(head) { - if(e) - *e = ret; - else - free(ret); - ret = 0; + ret = head->reply; + free(head); + + if(((XCBGenericRep *) ret)->response_type == 0) /* X error */ + { + if(e) + *e = ret; + else + free(ret); + ret = 0; + } } done: @@ -319,13 +352,13 @@ int _xcb_in_init(_xcb_in *in) in->queue_len = 0; in->request_read = 0; - in->current_reply = _xcb_queue_new(); in->replies = _xcb_map_new(); in->readers = _xcb_list_new(); - if(!in->current_reply || !in->replies || !in->readers) + if(!in->replies || !in->readers) return 0; + in->current_reply_tail = &in->current_reply; in->events_tail = &in->events; in->pending_replies_tail = &in->pending_replies; @@ -335,8 +368,8 @@ int _xcb_in_init(_xcb_in *in) void _xcb_in_destroy(_xcb_in *in) { pthread_cond_destroy(&in->event_cond); - _xcb_queue_delete(in->current_reply, free); - _xcb_map_delete(in->replies, free); + free_reply_list(in->current_reply); + _xcb_map_delete(in->replies, (void (*)(void *)) free_reply_list); _xcb_list_delete(in->readers, 0); while(in->events) { diff --git a/src/xcb_list.c b/src/xcb_list.c index 5b2edc0..6a72c16 100644 --- a/src/xcb_list.c +++ b/src/xcb_list.c @@ -144,16 +144,6 @@ void *_xcb_list_find(_xcb_list *list, int (*cmp)(const void *, const void *), co return 0; } -_xcb_queue *_xcb_queue_new(void) __attribute__ ((alias ("_xcb_list_new"))); -void _xcb_queue_delete(_xcb_queue *q, XCBListFreeFunc do_free) __attribute__ ((alias ("_xcb_list_delete"))); -int _xcb_queue_enqueue(_xcb_queue *q, void *data) __attribute__ ((alias ("_xcb_list_append"))); -void *_xcb_queue_dequeue(_xcb_queue *q) __attribute__ ((alias ("_xcb_list_remove_head"))); - -int _xcb_queue_is_empty(_xcb_queue *q) -{ - return q->head == 0; -} - typedef struct { unsigned int key; void *value; diff --git a/src/xcbint.h b/src/xcbint.h index 6a61d18..c508504 100644 --- a/src/xcbint.h +++ b/src/xcbint.h @@ -53,14 +53,6 @@ void *_xcb_list_remove_head(_xcb_list *list); void *_xcb_list_remove(_xcb_list *list, int (*cmp)(const void *, const void *), const void *data); void *_xcb_list_find(_xcb_list *list, int (*cmp)(const void *, const void *), const void *data); -typedef _xcb_list _xcb_queue; - -_xcb_queue *_xcb_queue_new(void); -void _xcb_queue_delete(_xcb_queue *q, XCBListFreeFunc do_free); -int _xcb_queue_enqueue(_xcb_queue *q, void *data); -void *_xcb_queue_dequeue(_xcb_queue *q); -int _xcb_queue_is_empty(_xcb_queue *q); - typedef _xcb_list _xcb_map; _xcb_map *_xcb_map_new(void); @@ -106,7 +98,8 @@ typedef struct _xcb_in { int queue_len; unsigned int request_read; - _xcb_queue *current_reply; + struct reply_list *current_reply; + struct reply_list **current_reply_tail; _xcb_map *replies; struct event_list *events; |