[Xcb-commit] reply

Julien Danjou jdanjou at kemper.freedesktop.org
Tue Sep 16 07:53:09 PDT 2008


 reply/Makefile.am  |    1 
 reply/reply.c      |  222 +++++++++++++++++++++++++++--------------------------
 reply/test_reply.c |   10 +-
 reply/xcb_reply.h  |   99 +++++++++++++++++++++--
 4 files changed, 208 insertions(+), 124 deletions(-)

New commits:
commit 22189c7092c008c39019a41e3b78eb58fff5334a
Author: Julien Danjou <julien at danjou.info>
Date:   Tue Sep 16 16:33:46 2008 +0200

    reply: rework and add some documentation
    
    Signed-off-by: Julien Danjou <julien at danjou.info>

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 at 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 at 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__ */


More information about the xcb-commit mailing list