[PATCH XCB] Add reference counting support for connections

Mike Blumenkrantz zmike at samsung.com
Thu Jun 11 11:23:00 PDT 2015


From: Josh Triplett <josh at joshtriplett.org>

Add a new xcb_reference function that adds a reference, and make
xcb_disconnect do nothing until the reference count falls to 0.

Commit by Josh Triplett and Jamey Sharp.

Signed-off-by: Josh Triplett <josh at joshtriplett.org>
Signed-off-by: Jamey Sharp <jamey at minilop.net>
Signed-off-by: Mike Blumenkrantz <zmike at osg.samsung.com>
---
 src/Makefile.am |  2 +-
 src/xcb.h       | 25 ++++++++++++++++++++-----
 src/xcb_conn.c  | 23 +++++++++++++++++++++++
 src/xcbint.h    |  4 ++++
 4 files changed, 48 insertions(+), 6 deletions(-)

diff --git a/src/Makefile.am b/src/Makefile.am
index 5a3c52a..d884b95 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -18,7 +18,7 @@ nodist_libxcb_la_SOURCES = xproto.c bigreq.c xc_misc.c
 # * If you add an interface, increment current and age and set
revision to 0. # * If you change or remove an interface, increment
current and set revision #   and age to 0.
-libxcb_la_LDFLAGS = -version-info 2:0:1 -no-undefined
@lt_enable_auto_import@ +libxcb_la_LDFLAGS = -version-info 3:0:2
-no-undefined @lt_enable_auto_import@ 
 XCB_LIBS = libxcb.la
 
diff --git a/src/xcb.h b/src/xcb.h
index 86eb1bc..1ca70fd 100644
--- a/src/xcb.h
+++ b/src/xcb.h
@@ -495,7 +495,7 @@ int xcb_connection_has_error(xcb_connection_t *c);
  * xcb_auth_info_t @p auth_info. The file descriptor @p fd is
  * bidirectionally connected to an X server. If the connection
  * should be unauthenticated, @p auth_info must be @c
- * NULL.
+ * NULL. The returned connection starts out with a single reference.
  *
  * Always returns a non-NULL pointer to a xcb_connection_t, even on
failure.
  * Callers need to use xcb_connection_has_error() to check for failure.
@@ -504,12 +504,23 @@ int xcb_connection_has_error(xcb_connection_t *c);
  */
 xcb_connection_t *xcb_connect_to_fd(int fd, xcb_auth_info_t
*auth_info); 
-/**
- * @brief Closes the connection.
+ /**
+ * @brief Adds another reference to a connection.
  * @param c: The connection.
  *
- * Closes the file descriptor and frees all memory associated with the
- * connection @c c. If @p c is @c NULL, nothing is done.
+ * Adds a reference to the connection @p c; xcb_disconnect will not
close the
+ * connection until it has no more outstanding references.
+ */
+xcb_connection_t *xcb_reference(xcb_connection_t *c);
+
+
+/**
++ * @brief Removes a reference to a connection and closes it if it has
no more references. ++ * @param c: The connection.
++ *
++ * Removes one reference to the connection @p c. If that was the last
++ * reference, closes the file descriptor and frees all memory
associated ++ * with the connection @p c. If @p c is @c NULL, nothing
is done. */
 void xcb_disconnect(xcb_connection_t *c);
 
@@ -551,6 +562,8 @@ int xcb_parse_display(const char *name, char
**host, int *display, int *screen);
  * Callers need to use xcb_connection_has_error() to check for failure.
  * When finished, use xcb_disconnect() to close the connection and free
  * the structure.
+ *
+ * This function simply wraps xcb_connect_to_fd.
  */
 xcb_connection_t *xcb_connect(const char *displayname, int *screenp);
 
@@ -570,6 +583,8 @@ xcb_connection_t *xcb_connect(const char
*displayname, int *screenp);
  * Callers need to use xcb_connection_has_error() to check for failure.
  * When finished, use xcb_disconnect() to close the connection and free
  * the structure.
+ *
+ * This function simply wraps xcb_connect_to_fd.
  */
 xcb_connection_t *xcb_connect_to_display_with_auth_info(const char
*display, xcb_auth_info_t *auth, int *screen); 
diff --git a/src/xcb_conn.c b/src/xcb_conn.c
index 7d09637..98a2c54 100644
--- a/src/xcb_conn.c
+++ b/src/xcb_conn.c
@@ -349,9 +349,11 @@ xcb_connection_t *xcb_connect_to_fd(int fd,
xcb_auth_info_t *auth_info) }
 
     c->fd = fd;
+    c->refcount = 1;
 
     if(!(
         set_fd_flags(fd) &&
+        pthread_mutex_init(&c->reflock, 0) == 0 &&
         pthread_mutex_init(&c->iolock, 0) == 0 &&
         _xcb_in_init(&c->in) &&
         _xcb_out_init(&c->out) &&
@@ -368,11 +370,30 @@ xcb_connection_t *xcb_connect_to_fd(int fd,
xcb_auth_info_t *auth_info) return c;
 }
 
+xcb_connection_t *xcb_reference(xcb_connection_t *c)
+{
+    if(c == NULL || is_static_error_conn(c))
+        return c;
+
+    pthread_mutex_lock(&c->reflock);
+    c->refcount++;
+    pthread_mutex_unlock(&c->reflock);
+
+    return c;
+}
+
 void xcb_disconnect(xcb_connection_t *c)
 {
     if(c == NULL || is_static_error_conn(c))
         return;
 
+    pthread_mutex_lock(&c->reflock);
+    if(--c->refcount != 0)
+    {
+        pthread_mutex_unlock(&c->reflock);
+        return;
+    }
+
     free(c->setup);
 
     /* disallow further sends and receives */
@@ -386,6 +407,8 @@ void xcb_disconnect(xcb_connection_t *c)
     _xcb_ext_destroy(c);
     _xcb_xid_destroy(c);
 
+    pthread_mutex_unlock(&c->reflock);
+    pthread_mutex_destroy(&c->reflock);
     free(c);
 
 #ifdef _WIN32
diff --git a/src/xcbint.h b/src/xcbint.h
index f89deba..aa2c32e 100644
--- a/src/xcbint.h
+++ b/src/xcbint.h
@@ -195,6 +195,10 @@ struct xcb_connection_t {
     /* This must be the first field; see _xcb_conn_ret_error(). */
     int has_error;
 
+    /* reference counting */
+    pthread_mutex_t reflock;
+    int refcount;
+
     /* constant data */
     xcb_setup_t *setup;
     int fd;
-- 
2.4.2



More information about the xorg-devel mailing list