[cairo] [PATCH] Disconnect hooks.

Chris Wilson chris at chris-wilson.co.uk
Wed Oct 14 09:14:45 PDT 2009


---
 src/xcb.h      |   14 ++++++++++++++
 src/xcb_conn.c |   33 +++++++++++++++++++++++++++++++--
 src/xcb_ext.c  |    9 +++++----
 src/xcbint.h   |    9 +++++++++
 4 files changed, 59 insertions(+), 6 deletions(-)

diff --git a/src/xcb.h b/src/xcb.h
index f951276..be18b2f 100644
--- a/src/xcb.h
+++ b/src/xcb.h
@@ -395,6 +395,20 @@ xcb_connection_t *xcb_connect_to_fd(int fd, xcb_auth_info_t *auth_info);
  */
 void xcb_disconnect(xcb_connection_t *c);
 
+/**
+ * @brief Adds a callback to be called on disconnection.
+ * @param c: The connection.
+ * @param callback: The callback.
+ * @param closure: The data to be passed to the callback.
+ * @return 0 on failure, non 0 otherwise.
+ *
+ * Adds a callback that will be when the connection is closed.
+ */
+int xcb_add_disconnect_hook(xcb_connection_t *c,
+			    void (*callback) (xcb_connection_t *,
+					      void *closure),
+			    void (*closure));
+
 
 /* xcb_util.c */
 
diff --git a/src/xcb_conn.c b/src/xcb_conn.c
index 251d62e..34b8880 100644
--- a/src/xcb_conn.c
+++ b/src/xcb_conn.c
@@ -215,6 +215,7 @@ xcb_connection_t *xcb_connect_to_fd(int fd, xcb_auth_info_t *auth_info)
         return (xcb_connection_t *) &error_connection;
 
     c->fd = fd;
+    c->disconnect_hooks = NULL;
 
     if(!(
         set_fd_flags(fd) &&
@@ -236,8 +237,15 @@ xcb_connection_t *xcb_connect_to_fd(int fd, xcb_auth_info_t *auth_info)
 
 void xcb_disconnect(xcb_connection_t *c)
 {
-    if(c->has_error)
-        return;
+    if  (c == (xcb_connection_t *) &error_connection)
+	return;
+
+    while (c->disconnect_hooks != NULL) {
+	_xcb_hook *hook = c->disconnect_hooks;
+	c->disconnect_hooks = hook->next;
+	hook->callback (c, hook->closure);
+	free (hook);
+    }
 
     free(c->setup);
     close(c->fd);
@@ -252,6 +260,27 @@ void xcb_disconnect(xcb_connection_t *c)
     free(c);
 }
 
+int xcb_add_disconnect_hook(xcb_connection_t *c,
+			    void (*callback) (xcb_connection_t *,
+					      void *closure),
+			    void (*closure))
+{
+    _xcb_hook *hook;
+
+    if  (c == (xcb_connection_t *) &error_connection)
+	return 0;
+
+    hook = malloc (sizeof (_xcb_hook));
+    if (! hook)
+	return 0;
+
+    hook->callback = callback;
+    hook->closure = closure;
+    hook->next = c->disconnect_hooks;
+    c->disconnect_hooks = hook;
+    return 1;
+}
+
 /* Private interface */
 
 void _xcb_conn_shutdown(xcb_connection_t *c)
diff --git a/src/xcb_ext.c b/src/xcb_ext.c
index 68bb29b..d013781 100644
--- a/src/xcb_ext.c
+++ b/src/xcb_ext.c
@@ -62,10 +62,11 @@ static lazyreply *get_lazyreply(xcb_connection_t *c, xcb_extension_t *ext)
 
     lazyreply *data;
 
-    pthread_mutex_lock(&global_lock);
-    if(!ext->global_id)
-        ext->global_id = ++next_global_id;
-    pthread_mutex_unlock(&global_lock);
+    if(!ext->global_id) {
+	pthread_mutex_lock(&global_lock);
+	ext->global_id = ++next_global_id;
+	pthread_mutex_unlock(&global_lock);
+    }
 
     data = get_index(c, ext->global_id);
     if(data && data->tag == LAZY_NONE)
diff --git a/src/xcbint.h b/src/xcbint.h
index 154cca0..29ce018 100644
--- a/src/xcbint.h
+++ b/src/xcbint.h
@@ -172,6 +172,14 @@ void _xcb_ext_destroy(xcb_connection_t *c);
 
 /* xcb_conn.c */
 
+typedef struct _xcb_hook {
+    struct _xcb_hook *next;
+
+    void (*callback) (xcb_connection_t *connection,
+		      void *closure);
+    void *closure;
+} _xcb_hook;
+
 struct xcb_connection_t {
     int has_error;
 
@@ -187,6 +195,7 @@ struct xcb_connection_t {
     /* misc data */
     _xcb_ext ext;
     _xcb_xid xid;
+    _xcb_hook *disconnect_hooks;
 };
 
 void _xcb_conn_shutdown(xcb_connection_t *c);
-- 
1.6.4.3



More information about the cairo mailing list