Merge branch 'wait_for_special_event_with_timeout' into 'master'

WIP: xcb_wait_for_special_event_with_timeout()

See merge request xorg/lib/libxcb!9
This commit is contained in:
Uli Schlachter 2025-01-10 06:55:04 +00:00
commit 5c2c26695e
4 changed files with 72 additions and 3 deletions

View File

@ -361,6 +361,13 @@ xcb_generic_event_t *xcb_poll_for_special_event(xcb_connection_t *c,
*/ */
xcb_generic_event_t *xcb_wait_for_special_event(xcb_connection_t *c, xcb_generic_event_t *xcb_wait_for_special_event(xcb_connection_t *c,
xcb_special_event_t *se); xcb_special_event_t *se);
/**
* @brief Returns the next event from a special queue, blocking until one arrives
*/
xcb_generic_event_t *xcb_wait_for_special_event_with_timeout(xcb_connection_t *c,
xcb_special_event_t *se,
unsigned int millisecs_timeout);
/** /**
* @typedef typedef struct xcb_extension_t xcb_extension_t * @typedef typedef struct xcb_extension_t xcb_extension_t
*/ */

View File

@ -36,6 +36,7 @@
#include <fcntl.h> #include <fcntl.h>
#include <errno.h> #include <errno.h>
#include <limits.h> #include <limits.h>
#include <sys/time.h> /* I bet this does not work on Windows... */
#include "xcb.h" #include "xcb.h"
#include "xcbint.h" #include "xcbint.h"
@ -464,6 +465,11 @@ xcb_connection_t *_xcb_conn_ret_error(int err)
} }
int _xcb_conn_wait(xcb_connection_t *c, pthread_cond_t *cond, struct iovec **vector, int *count) int _xcb_conn_wait(xcb_connection_t *c, pthread_cond_t *cond, struct iovec **vector, int *count)
{
return _xcb_conn_timedwait(c, cond, vector, count, NULL, NULL);
}
int _xcb_conn_timedwait(xcb_connection_t *c, pthread_cond_t *cond, struct iovec **vector, int *count, struct timeval *now, struct timeval *deadline)
{ {
int ret; int ret;
#if USE_POLL #if USE_POLL
@ -475,7 +481,13 @@ int _xcb_conn_wait(xcb_connection_t *c, pthread_cond_t *cond, struct iovec **vec
/* If the thing I should be doing is already being done, wait for it. */ /* If the thing I should be doing is already being done, wait for it. */
if(count ? c->out.writing : c->in.reading) if(count ? c->out.writing : c->in.reading)
{ {
pthread_cond_wait(cond, &c->iolock); if(deadline) {
struct timespec spec;
spec.tv_sec = deadline->tv_sec;
spec.tv_nsec = deadline->tv_usec * 100;
pthread_cond_timedwait(cond, &c->iolock, &spec);
} else
pthread_cond_wait(cond, &c->iolock);
return 1; return 1;
} }
@ -507,7 +519,13 @@ int _xcb_conn_wait(xcb_connection_t *c, pthread_cond_t *cond, struct iovec **vec
pthread_mutex_unlock(&c->iolock); pthread_mutex_unlock(&c->iolock);
do { do {
#if USE_POLL #if USE_POLL
ret = poll(&fd, 1, -1); int timeout = -1;
if(deadline && now) {
struct timeval diff;
timersub(deadline, now, &diff);
timeout = now->tv_sec * 1000 + now->tv_usec / 1000;
}
ret = poll(&fd, 1, timeout);
/* If poll() returns an event we didn't expect, such as POLLNVAL, treat /* If poll() returns an event we didn't expect, such as POLLNVAL, treat
* it as if it failed. */ * it as if it failed. */
if(ret >= 0 && (fd.revents & ~fd.events)) if(ret >= 0 && (fd.revents & ~fd.events))
@ -516,7 +534,13 @@ int _xcb_conn_wait(xcb_connection_t *c, pthread_cond_t *cond, struct iovec **vec
break; break;
} }
#else #else
ret = select(c->fd + 1, &rfds, &wfds, 0, 0); struct timeval diff;
struct timeval *timeout = NULL;
if(deadline && now) {
timersub(deadline, now, &diff);
timeout = &diff;
}
ret = select(c->fd + 1, &rfds, &wfds, 0, timeout);
#endif #endif
} while (ret == -1 && errno == EINTR); } while (ret == -1 && errno == EINTR);
if(ret < 0) if(ret < 0)

View File

@ -34,6 +34,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <errno.h> #include <errno.h>
#include <sys/time.h> /* I bet this does not work on Windows... */
#if USE_POLL #if USE_POLL
#include <poll.h> #include <poll.h>
@ -789,6 +790,42 @@ xcb_generic_event_t *xcb_poll_for_special_event(xcb_connection_t *c,
return event; return event;
} }
xcb_generic_event_t *xcb_wait_for_special_event_with_timeout(xcb_connection_t *c,
xcb_special_event_t *se,
unsigned int millisecs_timeout)
{
struct timeval now, deadline, timeout;
special_list special;
xcb_generic_event_t *event;
if(c->has_error)
return 0;
timeout.tv_sec = millisecs_timeout / 1000;
timeout.tv_usec = (millisecs_timeout % 1000) * 1000;
gettimeofday(&now, NULL); // TODO: Check for errors?
timeradd(&now, &timeout, &deadline);
pthread_mutex_lock(&c->iolock);
insert_special(&c->in.special_waiters, &special, se);
/* get_special_event returns 0 on empty list. */
while(!(event = get_special_event(c, se))) {
if(timercmp(&deadline, &now, <))
break;
if(!_xcb_conn_timedwait(c, &se->special_event_cond, 0, 0, &now, &deadline))
break;
gettimeofday(&now, NULL); // TODO: Check for errors?
}
remove_special(&c->in.special_waiters, &special);
_xcb_in_wake_up_next_reader(c);
pthread_mutex_unlock(&c->iolock);
return event;
}
xcb_generic_event_t *xcb_wait_for_special_event(xcb_connection_t *c, xcb_generic_event_t *xcb_wait_for_special_event(xcb_connection_t *c,
xcb_special_event_t *se) xcb_special_event_t *se)
{ {

View File

@ -229,6 +229,7 @@ XCB_CONST_FUNCTION
xcb_connection_t *_xcb_conn_ret_error(int err); xcb_connection_t *_xcb_conn_ret_error(int err);
int _xcb_conn_wait(xcb_connection_t *c, pthread_cond_t *cond, struct iovec **vector, int *count); int _xcb_conn_wait(xcb_connection_t *c, pthread_cond_t *cond, struct iovec **vector, int *count);
int _xcb_conn_timedwait(xcb_connection_t *c, pthread_cond_t *cond, struct iovec **vector, int *count, struct timeval *now, struct timeval *deadline);
/* xcb_auth.c */ /* xcb_auth.c */