xcb_request_check: Hold the I/O lock while deciding to sync.

Signed-off-by: Jamey Sharp <jamey@minilop.net>
This commit is contained in:
Jamey Sharp 2010-10-09 12:32:05 -07:00
parent ee1bc1d28a
commit 3a74b5e7a1
3 changed files with 33 additions and 19 deletions

View File

@ -356,20 +356,10 @@ static int poll_for_reply(xcb_connection_t *c, unsigned int request, void **repl
return 1; return 1;
} }
/* Public interface */ static void *wait_for_reply(xcb_connection_t *c, unsigned int request, xcb_generic_error_t **e)
void *xcb_wait_for_reply(xcb_connection_t *c, unsigned int request, xcb_generic_error_t **e)
{ {
uint64_t widened_request;
void *ret = 0; void *ret = 0;
if(e) uint64_t widened_request = (c->out.request & UINT64_C(0xffffffff00000000)) | request;
*e = 0;
if(c->has_error)
return 0;
pthread_mutex_lock(&c->iolock);
widened_request = (c->out.request & UINT64_C(0xffffffff00000000)) | request;
if(widened_request > c->out.request) if(widened_request > c->out.request)
widened_request -= UINT64_C(1) << 32; widened_request -= UINT64_C(1) << 32;
@ -411,6 +401,21 @@ void *xcb_wait_for_reply(xcb_connection_t *c, unsigned int request, xcb_generic_
} }
_xcb_in_wake_up_next_reader(c); _xcb_in_wake_up_next_reader(c);
return ret;
}
/* Public interface */
void *xcb_wait_for_reply(xcb_connection_t *c, unsigned int request, xcb_generic_error_t **e)
{
void *ret;
if(e)
*e = 0;
if(c->has_error)
return 0;
pthread_mutex_lock(&c->iolock);
ret = wait_for_reply(c, request, e);
pthread_mutex_unlock(&c->iolock); pthread_mutex_unlock(&c->iolock);
return ret; return ret;
} }
@ -575,21 +580,20 @@ xcb_generic_event_t *xcb_poll_for_event(xcb_connection_t *c)
xcb_generic_error_t *xcb_request_check(xcb_connection_t *c, xcb_void_cookie_t cookie) xcb_generic_error_t *xcb_request_check(xcb_connection_t *c, xcb_void_cookie_t cookie)
{ {
/* FIXME: this could hold the lock to avoid syncing unnecessarily, but xcb_generic_error_t *ret = 0;
* that would require factoring the locking out of xcb_get_input_focus,
* xcb_get_input_focus_reply, and xcb_wait_for_reply. */
xcb_generic_error_t *ret;
void *reply; void *reply;
if(c->has_error) if(c->has_error)
return 0; return 0;
pthread_mutex_lock(&c->iolock);
if(XCB_SEQUENCE_COMPARE_32(cookie.sequence,>=,c->in.request_expected) if(XCB_SEQUENCE_COMPARE_32(cookie.sequence,>=,c->in.request_expected)
&& XCB_SEQUENCE_COMPARE_32(cookie.sequence,>,c->in.request_completed)) && XCB_SEQUENCE_COMPARE_32(cookie.sequence,>,c->in.request_completed))
{ {
free(xcb_get_input_focus_reply(c, xcb_get_input_focus(c), &ret)); _xcb_out_send_sync(c);
assert(!ret); _xcb_out_flush_to(c, c->out.request);
} }
reply = xcb_wait_for_reply(c, cookie.sequence, &ret); reply = wait_for_reply(c, cookie.sequence, &ret);
assert(!reply); assert(!reply);
pthread_mutex_unlock(&c->iolock);
return ret; return ret;
} }

View File

@ -343,6 +343,15 @@ int _xcb_out_send(xcb_connection_t *c, struct iovec *vector, int count)
return ret; return ret;
} }
void _xcb_out_send_sync(xcb_connection_t *c)
{
/* wait for other writing threads to get out of my way. */
while(c->out.writing)
pthread_cond_wait(&c->out.cond, &c->iolock);
get_socket_back(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)
{ {
assert(XCB_SEQUENCE_COMPARE(request, <=, c->out.request)); assert(XCB_SEQUENCE_COMPARE(request, <=, c->out.request));

View File

@ -107,6 +107,7 @@ int _xcb_out_init(_xcb_out *out);
void _xcb_out_destroy(_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);
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);