[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