[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