mirror of
https://gitlab.freedesktop.org/xorg/lib/libxcb.git
synced 2026-05-20 00:58:10 +02:00
Merge branch 'flush-immediately' into 'master'
Introduce xcb_flush_nonblock() See merge request xorg/lib/libxcb!82
This commit is contained in:
commit
05c3c6eedf
5 changed files with 58 additions and 30 deletions
10
src/xcb.h
10
src/xcb.h
|
|
@ -269,6 +269,16 @@ typedef struct xcb_auth_info_t {
|
|||
*/
|
||||
int xcb_flush(xcb_connection_t *c);
|
||||
|
||||
/**
|
||||
* @brief Forces any buffered output to be written to the server without blocking.
|
||||
* @param c The connection to the X server.
|
||||
* @return > @c 0 on success, <= @c 0 otherwise.
|
||||
*
|
||||
* Forces any buffered output to be written to the server. Does not block,
|
||||
* returns immediately with errno set to EAGAIN if the write would block.
|
||||
*/
|
||||
int xcb_flush_nonblock(xcb_connection_t *c);
|
||||
|
||||
/**
|
||||
* @brief Returns the maximum request length that this server accepts.
|
||||
* @param c The connection to the X server.
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@ static int write_setup(xcb_connection_t *c, xcb_auth_info_t *auth_info)
|
|||
assert(count <= (int) (sizeof(parts) / sizeof(*parts)));
|
||||
|
||||
pthread_mutex_lock(&c->iolock);
|
||||
ret = _xcb_out_send(c, parts, count);
|
||||
ret = _xcb_out_send(c, parts, count, 1);
|
||||
pthread_mutex_unlock(&c->iolock);
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -463,13 +463,14 @@ 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 timeout)
|
||||
{
|
||||
int ret;
|
||||
#if USE_POLL
|
||||
struct pollfd fd;
|
||||
#else
|
||||
fd_set rfds, wfds;
|
||||
struct timeval timeout_timeval;
|
||||
#endif
|
||||
|
||||
/* If the thing I should be doing is already being done, wait for it. */
|
||||
|
|
@ -507,7 +508,7 @@ 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);
|
||||
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))
|
||||
|
|
@ -516,7 +517,9 @@ 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);
|
||||
timeout_timeval.tv_sec = timeout / 1000;
|
||||
timeout_timeval.tv_usec = (timeout % 1000) * 1000;
|
||||
ret = select(c->fd + 1, &rfds, &wfds, 0, timeout >= 0 ? &timeout_timeval : 0);
|
||||
#endif
|
||||
} while (ret == -1 && errno == EINTR);
|
||||
if(ret < 0)
|
||||
|
|
|
|||
10
src/xcb_in.c
10
src/xcb_in.c
|
|
@ -511,7 +511,7 @@ static void *wait_for_reply(xcb_connection_t *c, uint64_t request, xcb_generic_e
|
|||
void *ret = 0;
|
||||
|
||||
/* If this request has not been written yet, write it. */
|
||||
if(c->out.return_socket || _xcb_out_flush_to(c, request))
|
||||
if(c->out.return_socket || _xcb_out_flush_to(c, request, 1))
|
||||
{
|
||||
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
|
||||
reader_list reader;
|
||||
|
|
@ -519,7 +519,7 @@ static void *wait_for_reply(xcb_connection_t *c, uint64_t request, xcb_generic_e
|
|||
insert_reader(&c->in.readers, &reader, request, &cond);
|
||||
|
||||
while(!poll_for_reply(c, request, &ret, e))
|
||||
if(!_xcb_conn_wait(c, &cond, 0, 0))
|
||||
if(!_xcb_conn_wait(c, &cond, 0, 0, -1))
|
||||
break;
|
||||
|
||||
remove_reader(&c->in.readers, &reader);
|
||||
|
|
@ -700,7 +700,7 @@ xcb_generic_event_t *xcb_wait_for_event(xcb_connection_t *c)
|
|||
pthread_mutex_lock(&c->iolock);
|
||||
/* get_event returns 0 on empty list. */
|
||||
while(!(ret = get_event(c)))
|
||||
if(!_xcb_conn_wait(c, &c->in.event_cond, 0, 0))
|
||||
if(!_xcb_conn_wait(c, &c->in.event_cond, 0, 0, -1))
|
||||
break;
|
||||
|
||||
_xcb_in_wake_up_next_reader(c);
|
||||
|
|
@ -750,7 +750,7 @@ xcb_generic_error_t *xcb_request_check(xcb_connection_t *c, xcb_void_cookie_t co
|
|||
}
|
||||
if (XCB_SEQUENCE_COMPARE(request, >=, c->out.request_expected_written))
|
||||
{
|
||||
_xcb_out_flush_to(c, c->out.request);
|
||||
_xcb_out_flush_to(c, c->out.request, 1);
|
||||
}
|
||||
}
|
||||
reply = wait_for_reply(c, request, &ret);
|
||||
|
|
@ -803,7 +803,7 @@ xcb_generic_event_t *xcb_wait_for_special_event(xcb_connection_t *c,
|
|||
|
||||
/* get_special_event returns 0 on empty list. */
|
||||
while(!(event = get_special_event(c, se)))
|
||||
if(!_xcb_conn_wait(c, &se->special_event_cond, 0, 0))
|
||||
if(!_xcb_conn_wait(c, &se->special_event_cond, 0, 0, -1))
|
||||
break;
|
||||
|
||||
remove_special(&c->in.special_waiters, &special);
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#ifdef _WIN32
|
||||
#include <io.h>
|
||||
|
|
@ -69,7 +70,7 @@ static inline void send_request(xcb_connection_t *c, int isvoid, enum workaround
|
|||
vector[0].iov_base = c->out.queue;
|
||||
vector[0].iov_len = c->out.queue_len;
|
||||
c->out.queue_len = 0;
|
||||
_xcb_out_send(c, vector, count);
|
||||
_xcb_out_send(c, vector, count, 1);
|
||||
}
|
||||
|
||||
static void send_sync(xcb_connection_t *c)
|
||||
|
|
@ -204,7 +205,7 @@ static void send_fds(xcb_connection_t *c, int *fds, unsigned int num_fds)
|
|||
/* XXX: if c->out.writing > 0, this releases the iolock and
|
||||
* potentially allows other threads to interfere with their own fds.
|
||||
*/
|
||||
_xcb_out_flush_to(c, c->out.request);
|
||||
_xcb_out_flush_to(c, c->out.request, 1);
|
||||
|
||||
if (c->out.out_fd.nfd == XCB_MAX_PASS_FD) {
|
||||
/* We need some request to send FDs with */
|
||||
|
|
@ -385,7 +386,7 @@ int xcb_take_socket(xcb_connection_t *c, void (*return_socket)(void *closure), v
|
|||
* write requests, so keep flushing until we're done
|
||||
*/
|
||||
do
|
||||
ret = _xcb_out_flush_to(c, c->out.request);
|
||||
ret = _xcb_out_flush_to(c, c->out.request, 1);
|
||||
while (ret && c->out.request != c->out.request_written);
|
||||
if(ret)
|
||||
{
|
||||
|
|
@ -413,20 +414,30 @@ int xcb_writev(xcb_connection_t *c, struct iovec *vector, int count, uint64_t re
|
|||
return 0;
|
||||
pthread_mutex_lock(&c->iolock);
|
||||
c->out.request += requests;
|
||||
ret = _xcb_out_send(c, vector, count);
|
||||
ret = _xcb_out_send(c, vector, count, 1);
|
||||
pthread_mutex_unlock(&c->iolock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int flush(xcb_connection_t *c, int block)
|
||||
{
|
||||
int ret;
|
||||
if(c->has_error)
|
||||
return 0;
|
||||
pthread_mutex_lock(&c->iolock);
|
||||
ret = _xcb_out_flush_to(c, c->out.request, block);
|
||||
pthread_mutex_unlock(&c->iolock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int xcb_flush(xcb_connection_t *c)
|
||||
{
|
||||
int ret;
|
||||
if(c->has_error)
|
||||
return 0;
|
||||
pthread_mutex_lock(&c->iolock);
|
||||
ret = _xcb_out_flush_to(c, c->out.request);
|
||||
pthread_mutex_unlock(&c->iolock);
|
||||
return ret;
|
||||
return flush(c, 1);
|
||||
}
|
||||
|
||||
int xcb_flush_nonblock(xcb_connection_t *c)
|
||||
{
|
||||
return flush(c, 0);
|
||||
}
|
||||
|
||||
/* Private interface */
|
||||
|
|
@ -463,13 +474,17 @@ void _xcb_out_destroy(_xcb_out *out)
|
|||
pthread_cond_destroy(&out->socket_cond);
|
||||
}
|
||||
|
||||
int _xcb_out_send(xcb_connection_t *c, struct iovec *vector, int count)
|
||||
int _xcb_out_send(xcb_connection_t *c, struct iovec *vector, int count, int block)
|
||||
{
|
||||
int timeout = block ? -1 : 0;
|
||||
int ret = 1;
|
||||
while(ret && count)
|
||||
ret = _xcb_conn_wait(c, &c->out.cond, &vector, &count);
|
||||
c->out.request_written = c->out.request;
|
||||
c->out.request_expected_written = c->in.request_expected;
|
||||
errno = 0;
|
||||
while(ret && count && errno != EAGAIN)
|
||||
ret = _xcb_conn_wait(c, &c->out.cond, &vector, &count, timeout);
|
||||
if (count == 0) {
|
||||
c->out.request_written = c->out.request;
|
||||
c->out.request_expected_written = c->in.request_expected;
|
||||
}
|
||||
pthread_cond_broadcast(&c->out.cond);
|
||||
_xcb_in_wake_up_next_reader(c);
|
||||
return ret;
|
||||
|
|
@ -481,7 +496,7 @@ void _xcb_out_send_sync(xcb_connection_t *c)
|
|||
send_sync(c);
|
||||
}
|
||||
|
||||
int _xcb_out_flush_to(xcb_connection_t *c, uint64_t request)
|
||||
int _xcb_out_flush_to(xcb_connection_t *c, uint64_t request, int block)
|
||||
{
|
||||
assert(XCB_SEQUENCE_COMPARE(request, <=, c->out.request));
|
||||
if(XCB_SEQUENCE_COMPARE(c->out.request_written, >=, request))
|
||||
|
|
@ -492,7 +507,7 @@ int _xcb_out_flush_to(xcb_connection_t *c, uint64_t request)
|
|||
vec.iov_base = c->out.queue;
|
||||
vec.iov_len = c->out.queue_len;
|
||||
c->out.queue_len = 0;
|
||||
return _xcb_out_send(c, &vec, 1);
|
||||
return _xcb_out_send(c, &vec, 1, block);
|
||||
}
|
||||
while(c->out.writing)
|
||||
pthread_cond_wait(&c->out.cond, &c->iolock);
|
||||
|
|
|
|||
|
|
@ -128,9 +128,9 @@ typedef struct _xcb_out {
|
|||
int _xcb_out_init(_xcb_out *out);
|
||||
void _xcb_out_destroy(_xcb_out *out);
|
||||
|
||||
int _xcb_out_send(xcb_connection_t *c, struct iovec *vector, int count);
|
||||
int _xcb_out_send(xcb_connection_t *c, struct iovec *vector, int count, int timeout);
|
||||
void _xcb_out_send_sync(xcb_connection_t *c);
|
||||
int _xcb_out_flush_to(xcb_connection_t *c, uint64_t request);
|
||||
int _xcb_out_flush_to(xcb_connection_t *c, uint64_t request, int timeout);
|
||||
|
||||
|
||||
/* xcb_in.c */
|
||||
|
|
@ -226,7 +226,7 @@ void _xcb_conn_shutdown(xcb_connection_t *c, int err);
|
|||
XCB_CONST_FUNCTION
|
||||
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 timeout);
|
||||
|
||||
|
||||
/* xcb_auth.c */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue