[Xcb] [PATCH] Add special events file descriptor.
Julien Danjou
julien at danjou.info
Thu Aug 14 05:17:38 PDT 2008
Add 2 file descritpors created with pipe(7) in the xcb_connection_t data
structure.
Upon each new events which is placed in the event queue, the writable
file descriptor is written with the size of the data read.
The readable file descriptor is accessible from the application by
calling xcb_get_event_file_descriptor(). It can then be used as an event
file descriptor in a select() or poll() and assure that no event will be
missed.
To avoid pipe fill up, the data that have been written on packet
receival are read and discarded.
Signed-off-by: Julien Danjou <julien at danjou.info>
---
src/xcb.h | 14 ++++++++++++++
src/xcb_conn.c | 22 ++++++++++++++++++++++
src/xcb_in.c | 8 ++++++++
src/xcbint.h | 2 +-
4 files changed, 45 insertions(+), 1 deletions(-)
diff --git a/src/xcb.h b/src/xcb.h
index d24ef95..5e497ae 100644
--- a/src/xcb.h
+++ b/src/xcb.h
@@ -354,6 +354,20 @@ const xcb_setup_t *xcb_get_setup(xcb_connection_t *c);
int xcb_get_file_descriptor(xcb_connection_t *c);
/**
+ * @brief Access the event file descriptor of the connection.
+ * event will be missed by the watcher.
+ * @param c: The connection.
+ * @return The event file descriptor.
+ *
+ * Accessor for a special file descriptor which is written when new events
+ * are received. Upon each event, the number of data read on the connection
+ * file descriptor is written on it.
+ * This can be watched in a select() or poll() loop and assure no event will
+ * be missed, contrary to the connection file descriptor.
+ */
+int xcb_get_event_file_descriptor(xcb_connection_t *c);
+
+/**
* @brief Test whether the connection has shut down due to a fatal error.
* @param c: The connection.
* @return 1 if the connection is in an error state; 0 otherwise.
diff --git a/src/xcb_conn.c b/src/xcb_conn.c
index e7856c3..a08cee9 100644
--- a/src/xcb_conn.c
+++ b/src/xcb_conn.c
@@ -193,6 +193,16 @@ static int write_vec(xcb_connection_t *c, struct iovec **vector, int *count)
return 1;
}
+static int eventfd_setup(xcb_connection_t *c)
+{
+ int fd[2];
+ if(pipe(fd) < 0)
+ return 0;
+ c->eventfd_r = fd[0];
+ c->eventfd_w = fd[1];
+ return 1;
+}
+
/* Public interface */
const xcb_setup_t *xcb_get_setup(xcb_connection_t *c)
@@ -211,6 +221,13 @@ int xcb_get_file_descriptor(xcb_connection_t *c)
return c->fd;
}
+int xcb_get_event_file_descriptor(xcb_connection_t *c)
+{
+ if(c->has_error)
+ return -1;
+ return c->eventfd_r;
+}
+
int xcb_connection_has_error(xcb_connection_t *c)
{
/* doesn't need locking because it's read and written atomically. */
@@ -235,6 +252,9 @@ xcb_connection_t *xcb_connect_to_fd(int fd, xcb_auth_info_t *auth_info)
_xcb_out_init(&c->out) &&
write_setup(c, auth_info) &&
read_setup(c) &&
+ eventfd_setup(c) &&
+ set_fd_flags(c->eventfd_w) &&
+ set_fd_flags(c->eventfd_r) &&
_xcb_ext_init(c) &&
_xcb_xid_init(c)
))
@@ -253,6 +273,8 @@ void xcb_disconnect(xcb_connection_t *c)
free(c->setup);
close(c->fd);
+ close(c->eventfd_w);
+ close(c->eventfd_r);
pthread_mutex_destroy(&c->iolock);
_xcb_xlib_destroy(&c->xlib);
diff --git a/src/xcb_in.c b/src/xcb_in.c
index 31a1e60..93359b1 100644
--- a/src/xcb_in.c
+++ b/src/xcb_in.c
@@ -522,7 +522,15 @@ int _xcb_in_read(xcb_connection_t *c)
while(read_packet(c))
/* empty */;
if((n > 0) || (n < 0 && errno == EAGAIN))
+ {
+ int r;
+ /* read last written data if any,
+ * this avoids filling the kernel pipe buffer */
+ read(c->eventfd_r, &r, sizeof(r));
+ /* trigger event on eventfd */
+ write(c->eventfd_w, &n, sizeof(n));
return 1;
+ }
_xcb_conn_shutdown(c);
return 0;
}
diff --git a/src/xcbint.h b/src/xcbint.h
index ab0264f..a0f7787 100644
--- a/src/xcbint.h
+++ b/src/xcbint.h
@@ -169,7 +169,7 @@ struct xcb_connection_t {
/* constant data */
xcb_setup_t *setup;
- int fd;
+ int fd, eventfd_r, eventfd_w;
/* I/O data */
pthread_mutex_t iolock;
--
1.5.6.3
More information about the Xcb
mailing list