WIP: xcb_wait_for_special_event_with_timeout()

This surely has portability problems and is ugly since it works with
three different representations (timeout in milliseconds, deadline as
timeval, deadline as timespec). Also, this is completely untested. But
at least its a start.
This commit is contained in:
Uli Schlachter 2020-07-11 08:10:25 +02:00
parent 704e0a91b1
commit 6d17ed9f62
4 changed files with 72 additions and 3 deletions

View File

@ -337,6 +337,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_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
*/

View File

@ -37,6 +37,7 @@
#include <fcntl.h>
#include <errno.h>
#include <limits.h>
#include <sys/time.h> /* I bet this does not work on Windows... */
#include "xcb.h"
#include "xcbint.h"
@ -434,6 +435,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)
{
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;
#if USE_POLL
@ -445,7 +451,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(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;
}
@ -477,7 +489,13 @@ int _xcb_conn_wait(xcb_connection_t *c, pthread_cond_t *cond, struct iovec **vec
pthread_mutex_unlock(&c->iolock);
do {
#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
* it as if it failed. */
if(ret >= 0 && (fd.revents & ~fd.events))
@ -486,7 +504,13 @@ int _xcb_conn_wait(xcb_connection_t *c, pthread_cond_t *cond, struct iovec **vec
break;
}
#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
} while (ret == -1 && errno == EINTR);
if(ret < 0)

View File

@ -35,6 +35,7 @@
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <sys/time.h> /* I bet this does not work on Windows... */
#if USE_POLL
#include <poll.h>
@ -778,6 +779,42 @@ xcb_generic_event_t *xcb_poll_for_special_event(xcb_connection_t *c,
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_special_event_t *se)
{

View File

@ -217,6 +217,7 @@ void _xcb_conn_shutdown(xcb_connection_t *c, 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_timedwait(xcb_connection_t *c, pthread_cond_t *cond, struct iovec **vector, int *count, struct timeval *now, struct timeval *deadline);
/* xcb_auth.c */