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:
parent
704e0a91b1
commit
6d17ed9f62
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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)
|
||||
|
|
37
src/xcb_in.c
37
src/xcb_in.c
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue