2
* Copyright © 2008 Julien Danjou <julien@danjou.info>
4
* Permission is hereby granted, free of charge, to any person
5
* obtaining a copy of this software and associated documentation
6
* files (the "Software"), to deal in the Software without
7
* restriction, including without limitation the rights to use, copy,
8
* modify, merge, publish, distribute, sublicense, and/or sell copies
9
* of the Software, and to permit persons to whom the Software is
10
* furnished to do so, subject to the following conditions:
12
* The above copyright notice and this permission notice shall be
13
* included in all copies or substantial portions of the Software.
15
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
19
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
20
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
* Except as contained in this notice, the names of the authors or
24
* their institutions shall not be used in advertising or otherwise to
25
* promote the sale, use or other dealings in this Software without
26
* prior written authorization from the authors.
4
30
#include <xcb/xcbext.h>
9
generic_reply_handler handler;
14
struct reply_handlers {
22
reply_handlers_t *alloc_reply_handlers(xcb_connection_t *c)
24
reply_handlers_t *ret = calloc(1, sizeof(reply_handlers_t));
27
static const pthread_mutex_t proto_lock = PTHREAD_MUTEX_INITIALIZER;
28
static const pthread_cond_t proto_cond = PTHREAD_COND_INITIALIZER;
29
ret->lock = proto_lock;
30
ret->cond = proto_cond;
36
void free_reply_handlers(reply_handlers_t *h)
41
xcb_connection_t *get_xcb_connection(reply_handlers_t *h)
46
static void insert_handler(reply_handlers_t *h, struct node *cur)
48
struct node **prev = &h->head;
49
while(*prev && (*prev)->request < cur->request)
50
prev = &(*prev)->next;
55
static void remove_handler(reply_handlers_t *h, struct node *cur)
57
struct node **prev = &h->head;
58
while(*prev && (*prev)->request < cur->request)
59
prev = &(*prev)->next;
60
if(!(*prev) || (*prev)->request != cur->request)
66
static int process_replies(reply_handlers_t *h, int block)
69
pthread_mutex_lock(&h->lock);
70
pthread_cleanup_push((void (*)(void *)) pthread_mutex_unlock, &h->lock);
73
struct node *cur = h->head;
74
xcb_generic_error_t *error;
76
pthread_mutex_unlock(&h->lock);
77
pthread_cleanup_push((void (*)(void *)) pthread_mutex_lock, &h->lock);
79
reply = xcb_wait_for_reply(h->c, cur->request, &error);
80
else if(!xcb_poll_for_reply(h->c, cur->request, &reply, &error))
84
cur->handler(cur->data, h->c, reply, error);
89
handled |= cur->handled;
90
pthread_cleanup_pop(1);
92
remove_handler(h, cur);
96
pthread_cond_wait(&h->cond, &h->lock);
101
pthread_cleanup_pop(1);
105
int poll_replies(reply_handlers_t *h)
108
return process_replies(h, 0);
111
static void *reply_thread(void *h)
113
process_replies(h, 1);
117
void start_reply_thread(reply_handlers_t *h)
119
pthread_create(&h->thread, 0, reply_thread, h);
122
void stop_reply_thread(reply_handlers_t *h)
124
pthread_cancel(h->thread);
125
pthread_join(h->thread, 0);
128
void add_reply_handler(reply_handlers_t *h, unsigned int request, generic_reply_handler handler, void *data)
130
struct node *cur = malloc(sizeof(struct node));
131
cur->request = request;
132
cur->handler = handler;
136
pthread_mutex_lock(&h->lock);
137
insert_handler(h, cur);
138
pthread_cond_broadcast(&h->cond);
139
pthread_mutex_unlock(&h->lock);
32
#include "xcb_reply.h"
35
xcb_reply_handlers_init(xcb_connection_t *c, xcb_reply_handlers_t *r)
37
static const pthread_mutex_t proto_lock = PTHREAD_MUTEX_INITIALIZER;
38
static const pthread_cond_t proto_cond = PTHREAD_COND_INITIALIZER;
46
xcb_reply_get_xcb_connection(xcb_reply_handlers_t *h)
52
insert_handler(xcb_reply_handlers_t *h, struct xcb_reply_node *cur)
54
struct xcb_reply_node **prev = &h->head;
55
while(*prev && (*prev)->request < cur->request)
56
prev = &(*prev)->next;
62
remove_handler(xcb_reply_handlers_t *h, struct xcb_reply_node *cur)
64
struct xcb_reply_node **prev = &h->head;
65
while(*prev && (*prev)->request < cur->request)
66
prev = &(*prev)->next;
67
if(!(*prev) || (*prev)->request != cur->request)
74
process_replies(xcb_reply_handlers_t *h, int block)
77
pthread_mutex_lock(&h->lock);
78
pthread_cleanup_push((void (*)(void *)) pthread_mutex_unlock, &h->lock);
81
struct xcb_reply_node *cur = h->head;
82
xcb_generic_error_t *error;
84
pthread_mutex_unlock(&h->lock);
85
pthread_cleanup_push((void (*)(void *)) pthread_mutex_lock, &h->lock);
87
reply = xcb_wait_for_reply(h->c, cur->request, &error);
88
else if(!xcb_poll_for_reply(h->c, cur->request, &reply, &error))
92
cur->handler(cur->data, h->c, reply, error);
97
handled |= cur->handled;
98
pthread_cleanup_pop(1);
100
remove_handler(h, cur);
104
pthread_cond_wait(&h->cond, &h->lock);
109
pthread_cleanup_pop(1);
114
reply_thread(void *h)
116
process_replies(h, 1);
121
xcb_reply_start_thread(xcb_reply_handlers_t *h)
123
pthread_create(&h->thread, 0, reply_thread, h);
127
xcb_reply_stop_thread(xcb_reply_handlers_t *h)
129
pthread_cancel(h->thread);
130
pthread_join(h->thread, 0);
134
xcb_reply_add_handler(xcb_reply_handlers_t *h, unsigned int request, xcb_generic_reply_handler_t handler, void *data)
136
struct xcb_reply_node *cur = malloc(sizeof(struct xcb_reply_node));
137
cur->request = request;
138
cur->handler = handler;
142
pthread_mutex_lock(&h->lock);
143
insert_handler(h, cur);
144
pthread_cond_broadcast(&h->cond);
145
pthread_mutex_unlock(&h->lock);