From: Josh Triplett <[email protected]> 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 <[email protected]> Signed-off-by: Jamey Sharp <[email protected]> Signed-off-by: Mike Blumenkrantz <[email protected]> --- 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 _______________________________________________ [email protected]: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel
