summaryrefslogtreecommitdiff
path: root/reply
diff options
context:
space:
mode:
authorJulien Danjou <julien@danjou.info>2008-09-16 16:33:46 +0200
committerJulien Danjou <julien@danjou.info>2008-09-16 16:52:02 +0200
commit22189c7092c008c39019a41e3b78eb58fff5334a (patch)
tree9c8f0c1146e19b58aad4e23ec85832c9a1b73280 /reply
parent17132de01495c95833c2e8bafd66210a64d157d2 (diff)
reply: rework and add some documentation
Signed-off-by: Julien Danjou <julien@danjou.info>
Diffstat (limited to 'reply')
-rw-r--r--reply/Makefile.am1
-rw-r--r--reply/reply.c222
-rw-r--r--reply/test_reply.c10
-rw-r--r--reply/xcb_reply.h99
4 files changed, 208 insertions, 124 deletions
diff --git a/reply/Makefile.am b/reply/Makefile.am
index 847d0f7..aa49773 100644
--- a/reply/Makefile.am
+++ b/reply/Makefile.am
@@ -12,6 +12,7 @@ XCB_REPLY_LIBS = libxcb-reply.la
libxcb_reply_la_SOURCES = reply.c
libxcb_reply_la_CPPFLAGS = $(XCB_CFLAGS)
libxcb_reply_la_LIBADD = $(XCB_LIBS) -lpthread
+libxcb_reply_la_LDFLAGS = -version-info 1:0:0
pkgconfig_DATA = xcb-reply.pc
diff --git a/reply/reply.c b/reply/reply.c
index 2072ae1..0322ae0 100644
--- a/reply/reply.c
+++ b/reply/reply.c
@@ -1,140 +1,146 @@
-#include "xcb_reply.h"
+/*
+ * Copyright (C) 2008 Julien Danjou <julien@danjou.info>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the names of the authors or
+ * their institutions shall not be used in advertising or otherwise to
+ * promote the sale, use or other dealings in this Software without
+ * prior written authorization from the authors.
+ */
#include <stdlib.h>
#include <xcb/xcbext.h>
-struct node {
- struct node *next;
- unsigned int request;
- generic_reply_handler handler;
- void *data;
- char handled;
-};
-
-struct reply_handlers {
- pthread_mutex_t lock;
- pthread_cond_t cond;
- struct node *head;
- xcb_connection_t *c;
- pthread_t thread;
-};
-
-reply_handlers_t *alloc_reply_handlers(xcb_connection_t *c)
-{
- reply_handlers_t *ret = calloc(1, sizeof(reply_handlers_t));
- if(ret)
- {
- static const pthread_mutex_t proto_lock = PTHREAD_MUTEX_INITIALIZER;
- static const pthread_cond_t proto_cond = PTHREAD_COND_INITIALIZER;
- ret->lock = proto_lock;
- ret->cond = proto_cond;
- ret->c = c;
- }
- return ret;
-}
-
-void free_reply_handlers(reply_handlers_t *h)
-{
- free(h);
-}
+#include "xcb_reply.h"
-xcb_connection_t *get_xcb_connection(reply_handlers_t *h)
+void
+xcb_reply_handlers_init(xcb_connection_t *c, xcb_reply_handlers_t *r)
{
- return h->c;
+ static const pthread_mutex_t proto_lock = PTHREAD_MUTEX_INITIALIZER;
+ static const pthread_cond_t proto_cond = PTHREAD_COND_INITIALIZER;
+ r->lock = proto_lock;
+ r->cond = proto_cond;
+ r->c = c;
+ r->head = NULL;
}
-static void insert_handler(reply_handlers_t *h, struct node *cur)
+xcb_connection_t *
+xcb_reply_get_xcb_connection(xcb_reply_handlers_t *h)
{
- struct node **prev = &h->head;
- while(*prev && (*prev)->request < cur->request)
- prev = &(*prev)->next;
- cur->next = *prev;
- *prev = cur;
+ return h->c;
}
-static void remove_handler(reply_handlers_t *h, struct node *cur)
+static void
+insert_handler(xcb_reply_handlers_t *h, struct xcb_reply_node *cur)
{
- struct node **prev = &h->head;
- while(*prev && (*prev)->request < cur->request)
- prev = &(*prev)->next;
- if(!(*prev) || (*prev)->request != cur->request)
- return;
- *prev = cur->next;
- free(cur);
+ struct xcb_reply_node **prev = &h->head;
+ while(*prev && (*prev)->request < cur->request)
+ prev = &(*prev)->next;
+ cur->next = *prev;
+ *prev = cur;
}
-static int process_replies(reply_handlers_t *h, int block)
+static void
+remove_handler(xcb_reply_handlers_t *h, struct xcb_reply_node *cur)
{
- int handled = 0;
- pthread_mutex_lock(&h->lock);
- pthread_cleanup_push((void (*)(void *)) pthread_mutex_unlock, &h->lock);
- while(1)
- {
- struct node *cur = h->head;
- xcb_generic_error_t *error;
- void *reply;
- pthread_mutex_unlock(&h->lock);
- pthread_cleanup_push((void (*)(void *)) pthread_mutex_lock, &h->lock);
- if(block)
- reply = xcb_wait_for_reply(h->c, cur->request, &error);
- else if(!xcb_poll_for_reply(h->c, cur->request, &reply, &error))
- return handled;
- if(reply || error)
- {
- cur->handler(cur->data, h->c, reply, error);
- cur->handled = 1;
- free(reply);
- free(error);
- }
- handled |= cur->handled;
- pthread_cleanup_pop(1);
- if(!reply)
- remove_handler(h, cur);
- if(!h->head)
- {
- if(block)
- pthread_cond_wait(&h->cond, &h->lock);
- else
- break;
- }
- }
- pthread_cleanup_pop(1);
- return handled;
+ struct xcb_reply_node **prev = &h->head;
+ while(*prev && (*prev)->request < cur->request)
+ prev = &(*prev)->next;
+ if(!(*prev) || (*prev)->request != cur->request)
+ return;
+ *prev = cur->next;
+ free(cur);
}
-int poll_replies(reply_handlers_t *h)
+static int
+process_replies(xcb_reply_handlers_t *h, int block)
{
- xcb_flush(h->c);
- return process_replies(h, 0);
+ int handled = 0;
+ pthread_mutex_lock(&h->lock);
+ pthread_cleanup_push((void (*)(void *)) pthread_mutex_unlock, &h->lock);
+ while(1)
+ {
+ struct xcb_reply_node *cur = h->head;
+ xcb_generic_error_t *error;
+ void *reply;
+ pthread_mutex_unlock(&h->lock);
+ pthread_cleanup_push((void (*)(void *)) pthread_mutex_lock, &h->lock);
+ if(block)
+ reply = xcb_wait_for_reply(h->c, cur->request, &error);
+ else if(!xcb_poll_for_reply(h->c, cur->request, &reply, &error))
+ return handled;
+ if(reply || error)
+ {
+ cur->handler(cur->data, h->c, reply, error);
+ cur->handled = 1;
+ free(reply);
+ free(error);
+ }
+ handled |= cur->handled;
+ pthread_cleanup_pop(1);
+ if(!reply)
+ remove_handler(h, cur);
+ if(!h->head)
+ {
+ if(block)
+ pthread_cond_wait(&h->cond, &h->lock);
+ else
+ break;
+ }
+ }
+ pthread_cleanup_pop(1);
+ return handled;
}
-static void *reply_thread(void *h)
+static void *
+reply_thread(void *h)
{
- process_replies(h, 1);
- return 0;
+ process_replies(h, 1);
+ return 0;
}
-void start_reply_thread(reply_handlers_t *h)
+void
+xcb_reply_start_thread(xcb_reply_handlers_t *h)
{
- pthread_create(&h->thread, 0, reply_thread, h);
+ pthread_create(&h->thread, 0, reply_thread, h);
}
-void stop_reply_thread(reply_handlers_t *h)
+void
+xcb_reply_stop_thread(xcb_reply_handlers_t *h)
{
- pthread_cancel(h->thread);
- pthread_join(h->thread, 0);
+ pthread_cancel(h->thread);
+ pthread_join(h->thread, 0);
}
-void add_reply_handler(reply_handlers_t *h, unsigned int request, generic_reply_handler handler, void *data)
+void
+xcb_reply_add_handler(xcb_reply_handlers_t *h, unsigned int request, xcb_generic_reply_handler_t handler, void *data)
{
- struct node *cur = malloc(sizeof(struct node));
- cur->request = request;
- cur->handler = handler;
- cur->data = data;
- cur->handled = 0;
+ struct xcb_reply_node *cur = malloc(sizeof(struct xcb_reply_node));
+ cur->request = request;
+ cur->handler = handler;
+ cur->data = data;
+ cur->handled = 0;
- pthread_mutex_lock(&h->lock);
- insert_handler(h, cur);
- pthread_cond_broadcast(&h->cond);
- pthread_mutex_unlock(&h->lock);
+ pthread_mutex_lock(&h->lock);
+ insert_handler(h, cur);
+ pthread_cond_broadcast(&h->cond);
+ pthread_mutex_unlock(&h->lock);
}
diff --git a/reply/test_reply.c b/reply/test_reply.c
index 8aee7d8..6f6a021 100644
--- a/reply/test_reply.c
+++ b/reply/test_reply.c
@@ -1,4 +1,3 @@
-#include <xcb/xcb.h>
#include "xcb_reply.h"
#include <string.h>
@@ -36,18 +35,19 @@ int main(int argc, char **argv)
int count = 10;
char *pattern = "*";
xcb_connection_t *c = xcb_connect(NULL, NULL);
- reply_handlers_t *h = alloc_reply_handlers(c);
+ xcb_reply_handlers_t h;
+ xcb_reply_handlers_init(c, &h);
if(argc > 1)
count = atoi(argv[1]);
if(argc > 2)
pattern = argv[2];
- add_reply_handler(h, xcb_list_fonts_with_info(c, count, strlen(pattern), pattern).sequence, fontinfo_handler, 0);
+ xcb_reply_add_handler(&h, xcb_list_fonts_with_info(c, count, strlen(pattern), pattern).sequence, fontinfo_handler, 0);
pthread_mutex_lock(&lock);
- start_reply_thread(h);
+ xcb_reply_start_thread(&h);
pthread_cond_wait(&cond, &lock);
- stop_reply_thread(h);
+ xcb_reply_stop_thread(&h);
pthread_mutex_unlock(&lock);
xcb_disconnect(c);
diff --git a/reply/xcb_reply.h b/reply/xcb_reply.h
index 8a9e71e..360f74a 100644
--- a/reply/xcb_reply.h
+++ b/reply/xcb_reply.h
@@ -1,32 +1,109 @@
+/*
+ * Copyright (C) 2008 Julien Danjou <julien@danjou.info>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the names of the authors or
+ * their institutions shall not be used in advertising or otherwise to
+ * promote the sale, use or other dealings in this Software without
+ * prior written authorization from the authors.
+ */
+
#ifndef __XCB_REPLY_H__
#define __XCB_REPLY_H__
#include <xcb/xcb.h>
#include <pthread.h>
-
#ifdef __cplusplus
extern "C" {
#endif
+typedef void (*xcb_generic_reply_handler_t)(void *data, xcb_connection_t *c, xcb_generic_reply_t *reply, xcb_generic_error_t *error);
+
+struct xcb_reply_node
+{
+ struct xcb_reply_node *next;
+ unsigned int request;
+ xcb_generic_reply_handler_t handler;
+ void *data;
+ char handled;
+};
+
+struct xcb_reply_handlers
+{
+ pthread_mutex_t lock;
+ pthread_cond_t cond;
+ struct xcb_reply_node *head;
+ xcb_connection_t *c;
+ pthread_t thread;
+};
-typedef struct reply_handlers reply_handlers_t;
-reply_handlers_t *alloc_reply_handlers(xcb_connection_t *c);
-void free_reply_handlers(reply_handlers_t *h);
-xcb_connection_t *get_xcb_connection(reply_handlers_t *h);
+typedef struct xcb_reply_handlers xcb_reply_handlers_t;
-int poll_replies(reply_handlers_t *h);
-void start_reply_thread(reply_handlers_t *h);
-void stop_reply_thread(reply_handlers_t *h);
+/**
+ * @brief Initialize a reply handlers structure.
+ * @param c The connection to the X server.
+ * @param h The reply handlers.
+ */
+void xcb_reply_handlers_init(xcb_connection_t *c, xcb_reply_handlers_t *h);
-typedef void (*generic_reply_handler)(void *data, xcb_connection_t *c, xcb_generic_reply_t *reply, xcb_generic_error_t *error);
+/**
+ * @brief Get the connection to the X server used in reply handlers.
+ * @param h The reply handlers data structure.
+ * @return The connection to the X server.
+ */
+xcb_connection_t *xcb_reply_get_xcb_connection(xcb_reply_handlers_t *h);
-void add_reply_handler(reply_handlers_t *h, unsigned int request, generic_reply_handler handler, void *data);
+/**
+ * @brief Poll for reply using reply handlers.
+ * @param h The reply handlers data structure.
+ * @return The value return by the handler callback function, or 0 if no
+ * handler was found.
+ */
+int xcb_reply_poll_for_reply(xcb_reply_handlers_t *h);
+/**
+ * @brief Start reply handling thread.
+ * This thread will run forever until it is stop with xcb_reply_stop_thread.
+ * @param h The reply handlers.
+ */
+void xcb_reply_start_thread(xcb_reply_handlers_t *h);
+
+/**
+ * @brief Stop reply handling thread.
+ * @param h The reply handlers.
+ */
+void xcb_reply_stop_thread(xcb_reply_handlers_t *h);
+
+/**
+ * @brief Add a reply handler.
+ * @param h The reply handlers data structure to fill.
+ * @param request The request identifier.
+ * @param handler The handler to call for this request.
+ * @param data Optional data passed to the callback function handling request.
+ */
+void xcb_reply_add_handler(xcb_reply_handlers_t *h, unsigned int request, xcb_generic_reply_handler_t handler, void *data);
#ifdef __cplusplus
}
#endif
-
#endif /* __XCB_REPLY_H__ */