[Xcb-commit] 24 commits - xcb
Jamey Sharp
jamey at kemper.freedesktop.org
Fri Mar 3 11:54:35 PST 2006
xcb/configure.ac | 1
xcb/src/c-client.xsl | 22 ++-
xcb/src/xcb.h | 4
xcb/src/xcb_ext.c | 45 +++----
xcb/src/xcb_in.c | 297 +++++++++++++++++++++++++++++++--------------------
xcb/src/xcb_list.c | 152 +++-----------------------
xcb/src/xcb_out.c | 166 ++++++++++++----------------
xcb/src/xcbext.h | 7 +
xcb/src/xcbint.h | 38 ++----
9 files changed, 337 insertions(+), 395 deletions(-)
New commits:
diff-tree 33b2dfeed52023b25ad98b4b2eadb8b10794afcc (from cc05d651c8dbb944f8e4bbad8d189ccaadaa65c5)
Author: Jamey Sharp <jamey at minilop.net>
Date: Fri Mar 3 11:08:10 2006 -0800
API/ABI change: XCBSendRequest returns the sequence number instead of using an out-parameter. Now 0 is a special sequence number indicating failure.
diff --git a/xcb/src/c-client.xsl b/xcb/src/c-client.xsl
index 1e37ea9..c35fe33 100644
--- a/xcb/src/c-client.xsl
+++ b/xcb/src/c-client.xsl
@@ -615,7 +615,7 @@ authorization from the authors.
<l>xcb_parts[<xsl:value-of select="3 + position() * 2"/>].iov_len = -xcb_parts[<xsl:value-of select="2 + position() * 2"/>].iov_len & 3;</l>
</xsl:for-each>
- <l>XCBSendRequest(c, &xcb_ret.sequence, <!--
+ <l>xcb_ret.sequence = XCBSendRequest(c, <!--
--><xsl:choose>
<xsl:when test="@has-reply">XCB_REQUEST_CHECKED</xsl:when>
<xsl:otherwise>0</xsl:otherwise>
diff --git a/xcb/src/xcb_in.c b/xcb/src/xcb_in.c
index cf7dbe7..973a0d2 100644
--- a/xcb/src/xcb_in.c
+++ b/xcb/src/xcb_in.c
@@ -238,6 +238,10 @@ void *XCBWaitForReply(XCBConnection *c,
if(e)
*e = 0;
+ /* If an error occurred when issuing the request, fail immediately. */
+ if(!request)
+ return 0;
+
pthread_mutex_lock(&c->iolock);
/* If this request has not been written yet, write it. */
diff --git a/xcb/src/xcb_out.c b/xcb/src/xcb_out.c
index b201565..367013a 100644
--- a/xcb/src/xcb_out.c
+++ b/xcb/src/xcb_out.c
@@ -69,15 +69,14 @@ CARD32 XCBGetMaximumRequestLength(XCBCon
return c->out.maximum_request_length;
}
-int XCBSendRequest(XCBConnection *c, unsigned int *request, int flags, struct iovec *vector, const XCBProtocolRequest *req)
+unsigned int XCBSendRequest(XCBConnection *c, int flags, struct iovec *vector, const XCBProtocolRequest *req)
{
- int ret;
+ unsigned int request;
CARD32 prefix[2];
int veclen = req->count;
enum workarounds workaround = WORKAROUND_NONE;
assert(c != 0);
- assert(request != 0);
assert(vector != 0);
assert(req->count > 0);
@@ -92,8 +91,8 @@ int XCBSendRequest(XCBConnection *c, uns
if(req->ext)
{
const XCBQueryExtensionRep *extension = XCBGetExtensionData(c, req->ext);
- /* TODO: better error handling here, please! */
- assert(extension && extension->present);
+ if(!(extension && extension->present))
+ return 0;
((CARD8 *) vector[0].iov_base)[0] = extension->major_opcode;
((CARD8 *) vector[0].iov_base)[1] = req->opcode;
}
@@ -148,20 +147,22 @@ int XCBSendRequest(XCBConnection *c, uns
if(req->isvoid && !force_sequence_wrap(c))
{
pthread_mutex_unlock(&c->iolock);
- return -1;
+ return 0;
}
/* wait for other writing threads to get out of my way. */
while(c->out.writing)
pthread_cond_wait(&c->out.cond, &c->iolock);
- *request = ++c->out.request;
+ request = ++c->out.request;
+ assert(request != 0);
- _xcb_in_expect_reply(c, *request, workaround, flags);
+ _xcb_in_expect_reply(c, request, workaround, flags);
- ret = _xcb_out_write_block(c, vector, veclen);
+ if(!_xcb_out_write_block(c, vector, veclen))
+ request = 0;
pthread_mutex_unlock(&c->iolock);
- return ret;
+ return request;
}
int XCBFlush(XCBConnection *c)
diff --git a/xcb/src/xcbext.h b/xcb/src/xcbext.h
index 72dff64..fb169cf 100644
--- a/xcb/src/xcbext.h
+++ b/xcb/src/xcbext.h
@@ -56,7 +56,7 @@ enum XCBSendRequestFlags {
XCB_REQUEST_RAW = 1 << 1
};
-int XCBSendRequest(XCBConnection *c, unsigned int *sequence, int flags, struct iovec *vector, const XCBProtocolRequest *request);
+unsigned int XCBSendRequest(XCBConnection *c, int flags, struct iovec *vector, const XCBProtocolRequest *request);
/* xcb_in.c */
diff-tree cc05d651c8dbb944f8e4bbad8d189ccaadaa65c5 (from 3023022c1005757b0dfa68253fcd6d797fe252f3)
Author: Jamey Sharp <jamey at minilop.net>
Date: Fri Mar 3 01:45:00 2006 -0800
Add 32-bit full_sequence fields to generic errors and events, so callers can always correlate events and errors with requests correctly.
diff --git a/xcb/src/xcb.h b/xcb/src/xcb.h
index 8dd308a..ee87a99 100644
--- a/xcb/src/xcb.h
+++ b/xcb/src/xcb.h
@@ -80,12 +80,16 @@ typedef struct {
BYTE response_type;
CARD8 pad0;
CARD16 sequence;
+ CARD32 pad[7];
+ CARD32 full_sequence;
} XCBGenericEvent;
typedef struct {
BYTE response_type;
BYTE error_code;
CARD16 sequence;
+ CARD32 pad[7];
+ CARD32 full_sequence;
} XCBGenericError;
typedef struct {
diff --git a/xcb/src/xcb_in.c b/xcb/src/xcb_in.c
index cacb220..cf7dbe7 100644
--- a/xcb/src/xcb_in.c
+++ b/xcb/src/xcb_in.c
@@ -133,7 +133,7 @@ static int read_packet(XCBConnection *c)
length += genrep.length * 4;
}
- buf = malloc(length);
+ buf = malloc(length + (genrep.response_type == 1 ? 0 : sizeof(CARD32)));
if(!buf)
return 0;
if(_xcb_in_read_block(c, buf, length) <= 0)
@@ -142,6 +142,9 @@ static int read_packet(XCBConnection *c)
return 0;
}
+ if(genrep.response_type != 1)
+ ((XCBGenericEvent *) buf)->full_sequence = c->in.request_read;
+
/* reply, or checked error */
if(genrep.response_type == 1 || (genrep.response_type == 0 && pend && (pend->flags & XCB_REQUEST_CHECKED)))
{
diff-tree 3023022c1005757b0dfa68253fcd6d797fe252f3 (from 802cf95fba43c47de9bb92c1cf618fe72d75ab94)
Author: Jamey Sharp <jamey at minilop.net>
Date: Thu Mar 2 23:39:38 2006 -0800
Tweak to previous API change: Require that spare iovecs fall before vector[0]. Leave vector in well-defined state.
diff --git a/xcb/src/c-client.xsl b/xcb/src/c-client.xsl
index 568e46c..1e37ea9 100644
--- a/xcb/src/c-client.xsl
+++ b/xcb/src/c-client.xsl
@@ -596,30 +596,30 @@ authorization from the authors.
mode="assign" />
<l />
- <l>xcb_parts[0].iov_base = &xcb_out;</l>
- <l>xcb_parts[0].iov_len = sizeof(xcb_out);</l>
- <l>xcb_parts[1].iov_base = 0;</l>
- <l>xcb_parts[1].iov_len = -xcb_parts[0].iov_len & 3;</l>
+ <l>xcb_parts[2].iov_base = &xcb_out;</l>
+ <l>xcb_parts[2].iov_len = sizeof(xcb_out);</l>
+ <l>xcb_parts[3].iov_base = 0;</l>
+ <l>xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;</l>
<xsl:for-each select="$struct/list">
- <l>xcb_parts[<xsl:value-of select="position() * 2"/>].iov_base = (void *) <!--
+ <l>xcb_parts[<xsl:value-of select="2 + position() * 2"/>].iov_base = (void *) <!--
--><xsl:value-of select="@name" />;</l>
- <l>xcb_parts[<xsl:value-of select="position() * 2"/>].iov_len = <!--
+ <l>xcb_parts[<xsl:value-of select="2 + position() * 2"/>].iov_len = <!--
--><xsl:apply-templates mode="output-expression" /><!--
--><xsl:if test="not(@type = 'void')">
<xsl:text> * sizeof(</xsl:text>
<xsl:value-of select="@type" />
<xsl:text>)</xsl:text>
</xsl:if>;</l>
- <l>xcb_parts[<xsl:value-of select="1 + position() * 2"/>].iov_base = 0;</l>
- <l>xcb_parts[<xsl:value-of select="1 + position() * 2"/>].iov_len = -xcb_parts[<xsl:value-of select="position() * 2"/>].iov_len & 3;</l>
+ <l>xcb_parts[<xsl:value-of select="3 + position() * 2"/>].iov_base = 0;</l>
+ <l>xcb_parts[<xsl:value-of select="3 + position() * 2"/>].iov_len = -xcb_parts[<xsl:value-of select="2 + position() * 2"/>].iov_len & 3;</l>
</xsl:for-each>
<l>XCBSendRequest(c, &xcb_ret.sequence, <!--
--><xsl:choose>
<xsl:when test="@has-reply">XCB_REQUEST_CHECKED</xsl:when>
<xsl:otherwise>0</xsl:otherwise>
- </xsl:choose>, xcb_parts, &xcb_req);</l>
+ </xsl:choose>, xcb_parts + 2, &xcb_req);</l>
<l>return xcb_ret;</l>
</xsl:template>
diff --git a/xcb/src/xcb_out.c b/xcb/src/xcb_out.c
index 78ec8ca..b201565 100644
--- a/xcb/src/xcb_out.c
+++ b/xcb/src/xcb_out.c
@@ -126,8 +126,7 @@ int XCBSendRequest(XCBConnection *c, uns
((CARD16 *) vector[0].iov_base)[1] = shortlen;
if(!shortlen)
{
- memmove(vector + 1, vector, veclen++ * sizeof(*vector));
- ++veclen;
+ --vector, ++veclen;
vector[0].iov_base = prefix;
vector[0].iov_len = sizeof(prefix);
prefix[0] = ((CARD32 *) vector[0].iov_base)[0];
@@ -237,12 +236,14 @@ int _xcb_out_write_block(XCBConnection *
{
memcpy(c->out.queue + c->out.queue_len, vector[0].iov_base, vector[0].iov_len);
c->out.queue_len += vector[0].iov_len;
+ vector[0].iov_base = (char *) vector[0].iov_base + vector[0].iov_len;
+ vector[0].iov_len = 0;
++vector, --count;
}
if(!count)
return 1;
- memmove(vector + 1, vector, count++ * sizeof(struct iovec));
+ --vector, ++count;
vector[0].iov_base = c->out.queue;
vector[0].iov_len = c->out.queue_len;
c->out.queue_len = 0;
diff-tree 802cf95fba43c47de9bb92c1cf618fe72d75ab94 (from a228d64747a5eb1198ebee3dd690a5f6a05cd93b)
Author: Jamey Sharp <jamey at minilop.net>
Date: Thu Mar 2 23:31:35 2006 -0800
assert() that XCBSendRequest was handed enough space to set opcodes and short length fields.
diff --git a/xcb/src/xcb_out.c b/xcb/src/xcb_out.c
index 054a2ae..78ec8ca 100644
--- a/xcb/src/xcb_out.c
+++ b/xcb/src/xcb_out.c
@@ -87,6 +87,7 @@ int XCBSendRequest(XCBConnection *c, uns
int i;
CARD16 shortlen = 0;
size_t longlen = 0;
+ assert(vector[0].iov_len >= 4);
/* set the major opcode, and the minor opcode for extensions */
if(req->ext)
{
diff-tree a228d64747a5eb1198ebee3dd690a5f6a05cd93b (from 8382c7fd4bbf94b87473df256852da3889ed6c6e)
Author: Jamey Sharp <jamey at minilop.net>
Date: Thu Mar 2 23:12:21 2006 -0800
Bugfix: The fixed-length part needs two iovecs reserved, just like all the other parts.
diff --git a/xcb/src/c-client.xsl b/xcb/src/c-client.xsl
index 45e2cfe..568e46c 100644
--- a/xcb/src/c-client.xsl
+++ b/xcb/src/c-client.xsl
@@ -567,7 +567,7 @@ authorization from the authors.
<xsl:variable name="struct"
select="$pass1/xcb/struct[@name=current()/@ref]" />
- <xsl:variable name="num-parts" select="1+count($struct/list)*2" />
+ <xsl:variable name="num-parts" select="(1+count($struct/list))*2" />
<l>static const XCBProtocolRequest xcb_req = {</l>
<indent>
diff-tree 8382c7fd4bbf94b87473df256852da3889ed6c6e (from 983134c147c7cdb4d1726a7adf061a2903a21d8e)
Author: Jamey Sharp <jamey at minilop.net>
Date: Thu Mar 2 23:05:08 2006 -0800
Use XPath position() function instead of xsl:number, to evaluate array indices while generating code for easier readability.
diff --git a/xcb/src/c-client.xsl b/xcb/src/c-client.xsl
index bee7275..45e2cfe 100644
--- a/xcb/src/c-client.xsl
+++ b/xcb/src/c-client.xsl
@@ -602,17 +602,17 @@ authorization from the authors.
<l>xcb_parts[1].iov_len = -xcb_parts[0].iov_len & 3;</l>
<xsl:for-each select="$struct/list">
- <l>xcb_parts[<xsl:number /> * 2].iov_base = (void *) <!--
+ <l>xcb_parts[<xsl:value-of select="position() * 2"/>].iov_base = (void *) <!--
--><xsl:value-of select="@name" />;</l>
- <l>xcb_parts[<xsl:number /> * 2].iov_len = <!--
+ <l>xcb_parts[<xsl:value-of select="position() * 2"/>].iov_len = <!--
--><xsl:apply-templates mode="output-expression" /><!--
--><xsl:if test="not(@type = 'void')">
<xsl:text> * sizeof(</xsl:text>
<xsl:value-of select="@type" />
<xsl:text>)</xsl:text>
</xsl:if>;</l>
- <l>xcb_parts[<xsl:number /> * 2 + 1].iov_base = 0;</l>
- <l>xcb_parts[<xsl:number /> * 2 + 1].iov_len = -xcb_parts[<xsl:number /> * 2].iov_len & 3;</l>
+ <l>xcb_parts[<xsl:value-of select="1 + position() * 2"/>].iov_base = 0;</l>
+ <l>xcb_parts[<xsl:value-of select="1 + position() * 2"/>].iov_len = -xcb_parts[<xsl:value-of select="position() * 2"/>].iov_len & 3;</l>
</xsl:for-each>
<l>XCBSendRequest(c, &xcb_ret.sequence, <!--
diff-tree 983134c147c7cdb4d1726a7adf061a2903a21d8e (from b71d0c6503d8a03610201f634bf8d76a07a2d79a)
Author: Jamey Sharp <jamey at minilop.net>
Date: Thu Mar 2 15:35:31 2006 -0800
API/ABI change: XCBSendRequest callers must pad to 4-byte boundaries now. When not in RAW mode, a null pointer for iov_base is replaced by up to 3 padding bytes.
diff --git a/xcb/configure.ac b/xcb/configure.ac
index a07a89e..5e4405c 100644
--- a/xcb/configure.ac
+++ b/xcb/configure.ac
@@ -45,7 +45,6 @@ AC_MSG_RESULT($XCBPROTO_XCBINCLUDEDIR)
AC_SUBST(XCBPROTO_XCBINCLUDEDIR)
AC_HEADER_STDC
-AC_FUNC_ALLOCA
AC_SEARCH_LIBS(gethostbyname, nsl)
AC_SEARCH_LIBS(connect, socket)
diff --git a/xcb/src/c-client.xsl b/xcb/src/c-client.xsl
index 3ab2889..bee7275 100644
--- a/xcb/src/c-client.xsl
+++ b/xcb/src/c-client.xsl
@@ -567,7 +567,7 @@ authorization from the authors.
<xsl:variable name="struct"
select="$pass1/xcb/struct[@name=current()/@ref]" />
- <xsl:variable name="num-parts" select="1+count($struct/list)" />
+ <xsl:variable name="num-parts" select="1+count($struct/list)*2" />
<l>static const XCBProtocolRequest xcb_req = {</l>
<indent>
@@ -586,7 +586,7 @@ authorization from the authors.
<l>};</l>
<l />
- <l>struct iovec xcb_parts[<xsl:value-of select="$num-parts" />];</l>
+ <l>struct iovec xcb_parts[<xsl:value-of select="$num-parts+2" />];</l>
<l><xsl:value-of select="../@type" /> xcb_ret;</l>
<l><xsl:value-of select="@ref" /> xcb_out;</l>
@@ -598,17 +598,21 @@ authorization from the authors.
<l />
<l>xcb_parts[0].iov_base = &xcb_out;</l>
<l>xcb_parts[0].iov_len = sizeof(xcb_out);</l>
+ <l>xcb_parts[1].iov_base = 0;</l>
+ <l>xcb_parts[1].iov_len = -xcb_parts[0].iov_len & 3;</l>
<xsl:for-each select="$struct/list">
- <l>xcb_parts[<xsl:number />].iov_base = (void *) <!--
+ <l>xcb_parts[<xsl:number /> * 2].iov_base = (void *) <!--
--><xsl:value-of select="@name" />;</l>
- <l>xcb_parts[<xsl:number />].iov_len = <!--
+ <l>xcb_parts[<xsl:number /> * 2].iov_len = <!--
--><xsl:apply-templates mode="output-expression" /><!--
--><xsl:if test="not(@type = 'void')">
<xsl:text> * sizeof(</xsl:text>
<xsl:value-of select="@type" />
<xsl:text>)</xsl:text>
</xsl:if>;</l>
+ <l>xcb_parts[<xsl:number /> * 2 + 1].iov_base = 0;</l>
+ <l>xcb_parts[<xsl:number /> * 2 + 1].iov_len = -xcb_parts[<xsl:number /> * 2].iov_len & 3;</l>
</xsl:for-each>
<l>XCBSendRequest(c, &xcb_ret.sequence, <!--
diff --git a/xcb/src/xcb_out.c b/xcb/src/xcb_out.c
index 42050f5..054a2ae 100644
--- a/xcb/src/xcb_out.c
+++ b/xcb/src/xcb_out.c
@@ -31,16 +31,6 @@
#include <string.h>
#include <errno.h>
-#ifndef __GNUC__
-# if HAVE_ALLOCA_H
-# include <alloca.h>
-# else
-# ifdef _AIX
- #pragma alloca
-# endif
-# endif
-#endif
-
#include "xcb.h"
#include "xcbext.h"
#include "xcbint.h"
@@ -81,12 +71,9 @@ CARD32 XCBGetMaximumRequestLength(XCBCon
int XCBSendRequest(XCBConnection *c, unsigned int *request, int flags, struct iovec *vector, const XCBProtocolRequest *req)
{
- static const char pad[3];
int ret;
- int i;
CARD32 prefix[2];
- struct iovec *padded;
- int padlen = 0;
+ int veclen = req->count;
enum workarounds workaround = WORKAROUND_NONE;
assert(c != 0);
@@ -94,18 +81,12 @@ int XCBSendRequest(XCBConnection *c, uns
assert(vector != 0);
assert(req->count > 0);
- padded =
-#ifdef HAVE_ALLOCA
- alloca
-#else
- malloc
-#endif
- ((req->count * 2 + 2) * sizeof(struct iovec));
-
if(!(flags & XCB_REQUEST_RAW))
{
+ static const char pad[3];
+ int i;
CARD16 shortlen = 0;
- CARD32 longlen = 0;
+ size_t longlen = 0;
/* set the major opcode, and the minor opcode for extensions */
if(req->ext)
{
@@ -120,7 +101,16 @@ int XCBSendRequest(XCBConnection *c, uns
/* put together the length field, possibly using BIGREQUESTS */
for(i = 0; i < req->count; ++i)
- longlen += (vector[i].iov_len + 3) >> 2;
+ {
+ longlen += vector[i].iov_len;
+ if(!vector[i].iov_base)
+ {
+ vector[i].iov_base = (caddr_t) pad;
+ assert(vector[i].iov_len <= sizeof(pad));
+ }
+ }
+ assert((longlen & 3) == 0);
+ longlen >>= 2;
if(longlen <= c->setup->maximum_request_length)
{
@@ -135,29 +125,18 @@ int XCBSendRequest(XCBConnection *c, uns
((CARD16 *) vector[0].iov_base)[1] = shortlen;
if(!shortlen)
{
- padded[0].iov_base = prefix;
- padded[0].iov_len = sizeof(prefix);
+ memmove(vector + 1, vector, veclen++ * sizeof(*vector));
+ ++veclen;
+ vector[0].iov_base = prefix;
+ vector[0].iov_len = sizeof(prefix);
prefix[0] = ((CARD32 *) vector[0].iov_base)[0];
prefix[1] = ++longlen;
- vector[0].iov_base = ((char *) vector[0].iov_base) + sizeof(CARD32);
- vector[0].iov_len -= sizeof(CARD32);
- padlen = 1;
+ vector[1].iov_base = ((char *) vector[1].iov_base) + sizeof(CARD32);
+ vector[1].iov_len -= sizeof(CARD32);
}
}
flags &= ~XCB_REQUEST_RAW;
- for(i = 0; i < req->count; ++i)
- {
- if(!vector[i].iov_len)
- continue;
- padded[padlen].iov_base = vector[i].iov_base;
- padded[padlen++].iov_len = vector[i].iov_len;
- if(!XCB_PAD(vector[i].iov_len))
- continue;
- padded[padlen].iov_base = (caddr_t) pad;
- padded[padlen++].iov_len = XCB_PAD(vector[i].iov_len);
- }
-
/* do we need to work around the X server bug described in glx.xml? */
if(req->ext && !req->isvoid && strcmp(req->ext->name, "GLX") &&
((req->opcode == 17 && ((CARD32 *) vector[0].iov_base)[0] == 0x10004) ||
@@ -169,9 +148,6 @@ int XCBSendRequest(XCBConnection *c, uns
if(req->isvoid && !force_sequence_wrap(c))
{
pthread_mutex_unlock(&c->iolock);
-#ifndef HAVE_ALLOCA
- free(padded);
-#endif
return -1;
}
@@ -183,12 +159,8 @@ int XCBSendRequest(XCBConnection *c, uns
_xcb_in_expect_reply(c, *request, workaround, flags);
- ret = _xcb_out_write_block(c, padded, padlen);
+ ret = _xcb_out_write_block(c, vector, veclen);
pthread_mutex_unlock(&c->iolock);
-#ifndef HAVE_ALLOCA
- free(padded);
-#endif
-
return ret;
}
diff-tree b71d0c6503d8a03610201f634bf8d76a07a2d79a (from f0abda69379612a35cdd9a95acd20d5bc8e8c279)
Author: Jamey Sharp <jamey at minilop.net>
Date: Thu Mar 2 13:49:00 2006 -0800
Separate notion of request-completed from current-request, and mark requests completed more aggressively. Detects some usage errors that are otherwise undetectable.
diff --git a/xcb/src/xcb_in.c b/xcb/src/xcb_in.c
index 9e629ba..cacb220 100644
--- a/xcb/src/xcb_in.c
+++ b/xcb/src/xcb_in.c
@@ -89,25 +89,30 @@ static int read_packet(XCBConnection *c)
{
int lastread = c->in.request_read;
c->in.request_read = (lastread & 0xffff0000) | genrep.sequence;
+ if(c->in.request_read < lastread)
+ c->in.request_read += 0x10000;
+
if(c->in.request_read != lastread)
{
- while(c->in.pending_replies && c->in.pending_replies->request < c->in.request_read)
- {
- pending_reply *oldpend = c->in.pending_replies;
- c->in.pending_replies = oldpend->next;
- if(!oldpend->next)
- c->in.pending_replies_tail = &c->in.pending_replies;
- free(oldpend);
- }
if(c->in.current_reply)
{
_xcb_map_put(c->in.replies, lastread, c->in.current_reply);
c->in.current_reply = 0;
c->in.current_reply_tail = &c->in.current_reply;
}
+ c->in.request_completed = c->in.request_read - 1;
+ }
+ if(genrep.response_type != 1) /* not reply: error or event */
+ c->in.request_completed = c->in.request_read; /* XXX: does event/error imply no more replies? */
+
+ while(c->in.pending_replies && c->in.pending_replies->request <= c->in.request_completed)
+ {
+ pending_reply *oldpend = c->in.pending_replies;
+ c->in.pending_replies = oldpend->next;
+ if(!oldpend->next)
+ c->in.pending_replies_tail = &c->in.pending_replies;
+ free(oldpend);
}
- if(c->in.request_read < lastread)
- c->in.request_read += 0x10000;
}
if(genrep.response_type == 0 || genrep.response_type == 1)
@@ -246,9 +251,10 @@ void *XCBWaitForReply(XCBConnection *c,
reader.next = *prev_reader;
*prev_reader = &reader;
- /* If this request has not been read yet, wait for it. */
- while(((signed int) (c->in.request_read - request) < 0 ||
- (c->in.request_read == request && !c->in.current_reply)))
+ /* If this request has not completed yet and has no reply waiting,
+ * wait for one. */
+ while(c->in.request_completed < request &&
+ !(c->in.request_read == request && c->in.current_reply))
if(!_xcb_conn_wait(c, /*should_write*/ 0, &cond))
goto done;
@@ -359,6 +365,7 @@ int _xcb_in_init(_xcb_in *in)
in->queue_len = 0;
in->request_read = 0;
+ in->request_completed = 0;
in->replies = _xcb_map_new();
if(!in->replies)
diff --git a/xcb/src/xcbint.h b/xcb/src/xcbint.h
index 0e24d72..3b51d2e 100644
--- a/xcb/src/xcbint.h
+++ b/xcb/src/xcbint.h
@@ -87,6 +87,7 @@ typedef struct _xcb_in {
int queue_len;
unsigned int request_read;
+ unsigned int request_completed;
struct reply_list *current_reply;
struct reply_list **current_reply_tail;
diff-tree f0abda69379612a35cdd9a95acd20d5bc8e8c279 (from 256e5cc673fc7d31935096e717cf7fe7fd438f6c)
Author: Jamey Sharp <jamey at minilop.net>
Date: Mon Feb 27 12:12:33 2006 -0800
Buffer a couple CARD32s on the stack instead of using an extra iovec. Also a bugfix: do not hold a reference to longlen after it goes out of scope.
diff --git a/xcb/src/xcb_out.c b/xcb/src/xcb_out.c
index b89af56..42050f5 100644
--- a/xcb/src/xcb_out.c
+++ b/xcb/src/xcb_out.c
@@ -84,6 +84,7 @@ int XCBSendRequest(XCBConnection *c, uns
static const char pad[3];
int ret;
int i;
+ CARD32 prefix[2];
struct iovec *padded;
int padlen = 0;
enum workarounds workaround = WORKAROUND_NONE;
@@ -99,7 +100,7 @@ int XCBSendRequest(XCBConnection *c, uns
#else
malloc
#endif
- ((req->count * 2 + 3) * sizeof(struct iovec));
+ ((req->count * 2 + 2) * sizeof(struct iovec));
if(!(flags & XCB_REQUEST_RAW))
{
@@ -134,14 +135,13 @@ int XCBSendRequest(XCBConnection *c, uns
((CARD16 *) vector[0].iov_base)[1] = shortlen;
if(!shortlen)
{
- padded[0].iov_base = vector[0].iov_base;
- padded[0].iov_len = sizeof(CARD32);
+ padded[0].iov_base = prefix;
+ padded[0].iov_len = sizeof(prefix);
+ prefix[0] = ((CARD32 *) vector[0].iov_base)[0];
+ prefix[1] = ++longlen;
vector[0].iov_base = ((char *) vector[0].iov_base) + sizeof(CARD32);
vector[0].iov_len -= sizeof(CARD32);
- ++longlen;
- padded[1].iov_base = &longlen;
- padded[1].iov_len = sizeof(CARD32);
- padlen = 2;
+ padlen = 1;
}
}
flags &= ~XCB_REQUEST_RAW;
diff-tree 256e5cc673fc7d31935096e717cf7fe7fd438f6c (from f2f70fca65419d11d9cd121bc749de86871dca33)
Author: Jamey Sharp <jamey at minilop.net>
Date: Mon Feb 27 11:03:13 2006 -0800
Add XCB_REQUEST_RAW flag for XCBSendRequest.
diff --git a/xcb/src/xcb_out.c b/xcb/src/xcb_out.c
index 762efbd..b89af56 100644
--- a/xcb/src/xcb_out.c
+++ b/xcb/src/xcb_out.c
@@ -86,8 +86,6 @@ int XCBSendRequest(XCBConnection *c, uns
int i;
struct iovec *padded;
int padlen = 0;
- CARD16 shortlen = 0;
- CARD32 longlen = 0;
enum workarounds workaround = WORKAROUND_NONE;
assert(c != 0);
@@ -95,37 +93,6 @@ int XCBSendRequest(XCBConnection *c, uns
assert(vector != 0);
assert(req->count > 0);
- /* set the major opcode, and the minor opcode for extensions */
- if(req->ext)
- {
- const XCBQueryExtensionRep *extension = XCBGetExtensionData(c, req->ext);
- /* TODO: better error handling here, please! */
- assert(extension && extension->present);
- ((CARD8 *) vector[0].iov_base)[0] = extension->major_opcode;
- ((CARD8 *) vector[0].iov_base)[1] = req->opcode;
-
- /* do we need to work around the X server bug described in glx.xml? */
- if(!req->isvoid && strcmp(req->ext->name, "GLX") &&
- ((req->opcode == 17 && ((CARD32 *) vector[0].iov_base)[0] == 0x10004) ||
- req->opcode == 21))
- workaround = WORKAROUND_GLX_GET_FB_CONFIGS_BUG;
- }
- else
- ((CARD8 *) vector[0].iov_base)[0] = req->opcode;
-
- /* put together the length field, possibly using BIGREQUESTS */
- for(i = 0; i < req->count; ++i)
- longlen += (vector[i].iov_len + 3) >> 2;
-
- if(longlen <= c->setup->maximum_request_length)
- {
- /* we don't need BIGREQUESTS. */
- shortlen = longlen;
- longlen = 0;
- }
- else if(longlen > XCBGetMaximumRequestLength(c))
- return 0; /* server can't take this; maybe need BIGREQUESTS? */
-
padded =
#ifdef HAVE_ALLOCA
alloca
@@ -133,19 +100,51 @@ int XCBSendRequest(XCBConnection *c, uns
malloc
#endif
((req->count * 2 + 3) * sizeof(struct iovec));
- /* set the length field. */
- ((CARD16 *) vector[0].iov_base)[1] = shortlen;
- if(!shortlen)
- {
- padded[0].iov_base = vector[0].iov_base;
- padded[0].iov_len = sizeof(CARD32);
- vector[0].iov_base = ((char *) vector[0].iov_base) + sizeof(CARD32);
- vector[0].iov_len -= sizeof(CARD32);
- ++longlen;
- padded[1].iov_base = &longlen;
- padded[1].iov_len = sizeof(CARD32);
- padlen = 2;
+
+ if(!(flags & XCB_REQUEST_RAW))
+ {
+ CARD16 shortlen = 0;
+ CARD32 longlen = 0;
+ /* set the major opcode, and the minor opcode for extensions */
+ if(req->ext)
+ {
+ const XCBQueryExtensionRep *extension = XCBGetExtensionData(c, req->ext);
+ /* TODO: better error handling here, please! */
+ assert(extension && extension->present);
+ ((CARD8 *) vector[0].iov_base)[0] = extension->major_opcode;
+ ((CARD8 *) vector[0].iov_base)[1] = req->opcode;
+ }
+ else
+ ((CARD8 *) vector[0].iov_base)[0] = req->opcode;
+
+ /* put together the length field, possibly using BIGREQUESTS */
+ for(i = 0; i < req->count; ++i)
+ longlen += (vector[i].iov_len + 3) >> 2;
+
+ if(longlen <= c->setup->maximum_request_length)
+ {
+ /* we don't need BIGREQUESTS. */
+ shortlen = longlen;
+ longlen = 0;
+ }
+ else if(longlen > XCBGetMaximumRequestLength(c))
+ return 0; /* server can't take this; maybe need BIGREQUESTS? */
+
+ /* set the length field. */
+ ((CARD16 *) vector[0].iov_base)[1] = shortlen;
+ if(!shortlen)
+ {
+ padded[0].iov_base = vector[0].iov_base;
+ padded[0].iov_len = sizeof(CARD32);
+ vector[0].iov_base = ((char *) vector[0].iov_base) + sizeof(CARD32);
+ vector[0].iov_len -= sizeof(CARD32);
+ ++longlen;
+ padded[1].iov_base = &longlen;
+ padded[1].iov_len = sizeof(CARD32);
+ padlen = 2;
+ }
}
+ flags &= ~XCB_REQUEST_RAW;
for(i = 0; i < req->count; ++i)
{
@@ -159,6 +158,12 @@ int XCBSendRequest(XCBConnection *c, uns
padded[padlen++].iov_len = XCB_PAD(vector[i].iov_len);
}
+ /* do we need to work around the X server bug described in glx.xml? */
+ if(req->ext && !req->isvoid && strcmp(req->ext->name, "GLX") &&
+ ((req->opcode == 17 && ((CARD32 *) vector[0].iov_base)[0] == 0x10004) ||
+ req->opcode == 21))
+ workaround = WORKAROUND_GLX_GET_FB_CONFIGS_BUG;
+
/* get a sequence number and arrange for delivery. */
pthread_mutex_lock(&c->iolock);
if(req->isvoid && !force_sequence_wrap(c))
diff --git a/xcb/src/xcbext.h b/xcb/src/xcbext.h
index ddbb77a..72dff64 100644
--- a/xcb/src/xcbext.h
+++ b/xcb/src/xcbext.h
@@ -52,7 +52,8 @@ typedef struct {
} XCBProtocolRequest;
enum XCBSendRequestFlags {
- XCB_REQUEST_CHECKED = 1 << 0
+ XCB_REQUEST_CHECKED = 1 << 0,
+ XCB_REQUEST_RAW = 1 << 1
};
int XCBSendRequest(XCBConnection *c, unsigned int *sequence, int flags, struct iovec *vector, const XCBProtocolRequest *request);
diff-tree f2f70fca65419d11d9cd121bc749de86871dca33 (from 92b9e540662ac0c7a7ccac519bd0524e4ef98898)
Author: Jamey Sharp <jamey at minilop.net>
Date: Mon Feb 27 10:53:08 2006 -0800
Bugfix: how about *not* leaking all pending_replies when no reply matches, as often happens with Xlib?
diff --git a/xcb/src/xcb_in.c b/xcb/src/xcb_in.c
index a805fa8..9e629ba 100644
--- a/xcb/src/xcb_in.c
+++ b/xcb/src/xcb_in.c
@@ -91,9 +91,9 @@ static int read_packet(XCBConnection *c)
c->in.request_read = (lastread & 0xffff0000) | genrep.sequence;
if(c->in.request_read != lastread)
{
- pending_reply *oldpend = c->in.pending_replies;
- if(oldpend && oldpend->request == lastread)
+ while(c->in.pending_replies && c->in.pending_replies->request < c->in.request_read)
{
+ pending_reply *oldpend = c->in.pending_replies;
c->in.pending_replies = oldpend->next;
if(!oldpend->next)
c->in.pending_replies_tail = &c->in.pending_replies;
diff-tree 92b9e540662ac0c7a7ccac519bd0524e4ef98898 (from b902269ede8708dbfe163834c4723fea66837f31)
Author: Jamey Sharp <jamey at minilop.net>
Date: Mon Feb 27 02:57:36 2006 -0800
Move test for other writing threads *before* allocating a sequence number.
diff --git a/xcb/src/xcb_out.c b/xcb/src/xcb_out.c
index 8eb8a7a..762efbd 100644
--- a/xcb/src/xcb_out.c
+++ b/xcb/src/xcb_out.c
@@ -170,6 +170,10 @@ int XCBSendRequest(XCBConnection *c, uns
return -1;
}
+ /* wait for other writing threads to get out of my way. */
+ while(c->out.writing)
+ pthread_cond_wait(&c->out.cond, &c->iolock);
+
*request = ++c->out.request;
_xcb_in_expect_reply(c, *request, workaround, flags);
@@ -250,8 +254,6 @@ int _xcb_out_write(XCBConnection *c)
int _xcb_out_write_block(XCBConnection *c, struct iovec *vector, size_t count)
{
- while(c->out.writing)
- pthread_cond_wait(&c->out.cond, &c->iolock);
assert(!c->out.vec && !c->out.vec_len);
while(count && c->out.queue_len + vector[0].iov_len < sizeof(c->out.queue))
{
diff-tree b902269ede8708dbfe163834c4723fea66837f31 (from 35b7030536321ab23e71eba12b15f4724c8590ab)
Author: Jamey Sharp <jamey at minilop.net>
Date: Mon Feb 27 02:14:48 2006 -0800
_xcb_list is no longer used, so remove it. Simplify _xcb_map.
diff --git a/xcb/src/xcb_list.c b/xcb/src/xcb_list.c
index 718a380..9854ead 100644
--- a/xcb/src/xcb_list.c
+++ b/xcb/src/xcb_list.c
@@ -32,20 +32,21 @@
typedef struct node {
struct node *next;
+ unsigned int key;
void *data;
} node;
-struct _xcb_list {
+struct _xcb_map {
node *head;
node **tail;
};
/* Private interface */
-_xcb_list *_xcb_list_new()
+_xcb_map *_xcb_map_new()
{
- _xcb_list *list;
- list = malloc(sizeof(_xcb_list));
+ _xcb_map *list;
+ list = malloc(sizeof(_xcb_map));
if(!list)
return 0;
list->head = 0;
@@ -53,7 +54,7 @@ _xcb_list *_xcb_list_new()
return list;
}
-void _xcb_list_delete(_xcb_list *list, XCBListFreeFunc do_free)
+void _xcb_map_delete(_xcb_map *list, XCBListFreeFunc do_free)
{
if(!list)
return;
@@ -68,32 +69,24 @@ void _xcb_list_delete(_xcb_list *list, X
free(list);
}
-int _xcb_list_append(_xcb_list *list, void *data)
+int _xcb_map_put(_xcb_map *list, unsigned int key, void *data)
{
- node *cur;
- cur = malloc(sizeof(node));
+ node *cur = malloc(sizeof(node));
if(!cur)
return 0;
+ cur->key = key;
cur->data = data;
cur->next = 0;
-
*list->tail = cur;
list->tail = &cur->next;
return 1;
}
-void *_xcb_list_peek_head(_xcb_list *list)
-{
- if(!list->head)
- return 0;
- return list->head->data;
-}
-
-void *_xcb_list_remove(_xcb_list *list, int (*cmp)(const void *, const void *), const void *data)
+void *_xcb_map_remove(_xcb_map *list, unsigned int key)
{
node **cur;
for(cur = &list->head; *cur; cur = &(*cur)->next)
- if(cmp(data, (*cur)->data))
+ if((*cur)->key == key)
{
node *tmp = *cur;
void *ret = (*cur)->data;
@@ -106,67 +99,3 @@ void *_xcb_list_remove(_xcb_list *list,
}
return 0;
}
-
-void *_xcb_list_find(_xcb_list *list, int (*cmp)(const void *, const void *), const void *data)
-{
- node *cur;
- for(cur = list->head; cur; cur = cur->next)
- if(cmp(data, cur->data))
- return cur->data;
- return 0;
-}
-
-typedef struct {
- unsigned int key;
- void *value;
-} map_pair;
-
-_xcb_map *_xcb_map_new(void) __attribute__ ((alias ("_xcb_list_new")));
-
-void _xcb_map_delete(_xcb_map *q, XCBListFreeFunc do_free)
-{
- if(!q)
- return;
- while(q->head)
- {
- node *cur = q->head;
- map_pair *pair = cur->data;
- if(do_free)
- do_free(pair->value);
- q->head = cur->next;
- free(pair);
- free(cur);
- }
- free(q);
-}
-
-int _xcb_map_put(_xcb_map *q, unsigned int key, void *data)
-{
- map_pair *cur = malloc(sizeof(map_pair));
- if(!cur)
- return 0;
- cur->key = key;
- cur->value = data;
- if(!_xcb_list_append(q, cur))
- {
- free(cur);
- return 0;
- }
- return 1;
-}
-
-static int match_map_pair(const void *key, const void *pair)
-{
- return ((map_pair *) pair)->key == *(unsigned int *) key;
-}
-
-void *_xcb_map_remove(_xcb_map *q, unsigned int key)
-{
- map_pair *cur = _xcb_list_remove(q, match_map_pair, &key);
- void *ret;
- if(!cur)
- return 0;
- ret = cur->value;
- free(cur);
- return ret;
-}
diff --git a/xcb/src/xcbint.h b/xcb/src/xcbint.h
index 67ec017..0e24d72 100644
--- a/xcb/src/xcbint.h
+++ b/xcb/src/xcbint.h
@@ -41,17 +41,9 @@ enum workarounds {
/* xcb_list.c */
-typedef struct _xcb_list _xcb_list;
typedef void (*XCBListFreeFunc)(void *);
-_xcb_list *_xcb_list_new(void);
-void _xcb_list_delete(_xcb_list *list, XCBListFreeFunc do_free);
-int _xcb_list_append(_xcb_list *list, void *data);
-void *_xcb_list_peek_head(_xcb_list *list);
-void *_xcb_list_remove(_xcb_list *list, int (*cmp)(const void *, const void *), const void *data);
-void *_xcb_list_find(_xcb_list *list, int (*cmp)(const void *, const void *), const void *data);
-
-typedef _xcb_list _xcb_map;
+typedef struct _xcb_map _xcb_map;
_xcb_map *_xcb_map_new(void);
void _xcb_map_delete(_xcb_map *q, XCBListFreeFunc do_free);
diff-tree 35b7030536321ab23e71eba12b15f4724c8590ab (from 2ca818c2050f8982dc89036e6a10561fe41cd377)
Author: Jamey Sharp <jamey at minilop.net>
Date: Mon Feb 27 01:43:07 2006 -0800
Replace readers generic list with hand-written typesafe version.
diff --git a/xcb/src/xcb_in.c b/xcb/src/xcb_in.c
index 8609702..a805fa8 100644
--- a/xcb/src/xcb_in.c
+++ b/xcb/src/xcb_in.c
@@ -56,19 +56,14 @@ typedef struct pending_reply {
typedef struct reader_list {
unsigned int request;
pthread_cond_t *data;
+ struct reader_list *next;
} reader_list;
-static int match_reply(const void *request, const void *data)
-{
- return ((reader_list *) data)->request == *(unsigned int *) request;
-}
-
static void wake_up_next_reader(XCBConnection *c)
{
- reader_list *cur = _xcb_list_peek_head(c->in.readers);
int pthreadret;
- if(cur)
- pthreadret = pthread_cond_signal(cur->data);
+ if(c->in.readers)
+ pthreadret = pthread_cond_signal(c->in.readers->data);
else
pthreadret = pthread_cond_signal(&c->in.event_cond);
assert(pthreadret == 0);
@@ -145,7 +140,7 @@ static int read_packet(XCBConnection *c)
/* reply, or checked error */
if(genrep.response_type == 1 || (genrep.response_type == 0 && pend && (pend->flags & XCB_REQUEST_CHECKED)))
{
- reader_list *reader = _xcb_list_find(c->in.readers, match_reply, &c->in.request_read);
+ reader_list *reader;
struct reply_list *cur = malloc(sizeof(struct reply_list));
if(!cur)
return 0;
@@ -153,8 +148,12 @@ static int read_packet(XCBConnection *c)
cur->next = 0;
*c->in.current_reply_tail = cur;
c->in.current_reply_tail = &cur->next;
- if(reader)
- pthread_cond_signal(reader->data);
+ for(reader = c->in.readers; reader && reader->request <= c->in.request_read; reader = reader->next)
+ if(reader->request == c->in.request_read)
+ {
+ pthread_cond_signal(reader->data);
+ break;
+ }
return 1;
}
@@ -225,6 +224,7 @@ void *XCBWaitForReply(XCBConnection *c,
{
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
reader_list reader;
+ reader_list **prev_reader;
struct reply_list *head;
void *ret = 0;
if(e)
@@ -237,12 +237,14 @@ void *XCBWaitForReply(XCBConnection *c,
if(!_xcb_out_flush(c))
goto done; /* error */
- if(_xcb_list_find(c->in.readers, match_reply, &request))
- goto done; /* error */
+ for(prev_reader = &c->in.readers; *prev_reader && (*prev_reader)->request <= request; prev_reader = &(*prev_reader)->next)
+ if((*prev_reader)->request == request)
+ goto done; /* error */
reader.request = request;
reader.data = &cond;
- _xcb_list_append(c->in.readers, &reader);
+ reader.next = *prev_reader;
+ *prev_reader = &reader;
/* If this request has not been read yet, wait for it. */
while(((signed int) (c->in.request_read - request) < 0 ||
@@ -283,7 +285,12 @@ void *XCBWaitForReply(XCBConnection *c,
}
done:
- _xcb_list_remove(c->in.readers, match_reply, &request);
+ for(prev_reader = &c->in.readers; *prev_reader && (*prev_reader)->request <= request; prev_reader = &(*prev_reader)->next)
+ if(*prev_reader == &reader)
+ {
+ *prev_reader = (*prev_reader)->next;
+ break;
+ }
pthread_cond_destroy(&cond);
wake_up_next_reader(c);
@@ -354,8 +361,7 @@ int _xcb_in_init(_xcb_in *in)
in->request_read = 0;
in->replies = _xcb_map_new();
- in->readers = _xcb_list_new();
- if(!in->replies || !in->readers)
+ if(!in->replies)
return 0;
in->current_reply_tail = &in->current_reply;
@@ -370,7 +376,6 @@ void _xcb_in_destroy(_xcb_in *in)
pthread_cond_destroy(&in->event_cond);
free_reply_list(in->current_reply);
_xcb_map_delete(in->replies, (void (*)(void *)) free_reply_list);
- _xcb_list_delete(in->readers, 0);
while(in->events)
{
struct event_list *e = in->events;
diff --git a/xcb/src/xcbint.h b/xcb/src/xcbint.h
index 85e79e3..67ec017 100644
--- a/xcb/src/xcbint.h
+++ b/xcb/src/xcbint.h
@@ -101,7 +101,7 @@ typedef struct _xcb_in {
_xcb_map *replies;
struct event_list *events;
struct event_list **events_tail;
- _xcb_list *readers;
+ struct reader_list *readers;
struct pending_reply *pending_replies;
struct pending_reply **pending_replies_tail;
diff-tree 2ca818c2050f8982dc89036e6a10561fe41cd377 (from 59621ada0c70041bd7625c0c21fa8a28d380b477)
Author: Jamey Sharp <jamey at minilop.net>
Date: Mon Feb 27 01:06:15 2006 -0800
Rename struct XCBReplyData to reader_list to follow my naming conventions and better reflect its purpose.
diff --git a/xcb/src/xcb_in.c b/xcb/src/xcb_in.c
index 92bc0bf..8609702 100644
--- a/xcb/src/xcb_in.c
+++ b/xcb/src/xcb_in.c
@@ -53,19 +53,19 @@ typedef struct pending_reply {
struct pending_reply *next;
} pending_reply;
-typedef struct XCBReplyData {
+typedef struct reader_list {
unsigned int request;
pthread_cond_t *data;
-} XCBReplyData;
+} reader_list;
static int match_reply(const void *request, const void *data)
{
- return ((XCBReplyData *) data)->request == *(unsigned int *) request;
+ return ((reader_list *) data)->request == *(unsigned int *) request;
}
static void wake_up_next_reader(XCBConnection *c)
{
- XCBReplyData *cur = _xcb_list_peek_head(c->in.readers);
+ reader_list *cur = _xcb_list_peek_head(c->in.readers);
int pthreadret;
if(cur)
pthreadret = pthread_cond_signal(cur->data);
@@ -145,7 +145,7 @@ static int read_packet(XCBConnection *c)
/* reply, or checked error */
if(genrep.response_type == 1 || (genrep.response_type == 0 && pend && (pend->flags & XCB_REQUEST_CHECKED)))
{
- XCBReplyData *reader = _xcb_list_find(c->in.readers, match_reply, &c->in.request_read);
+ reader_list *reader = _xcb_list_find(c->in.readers, match_reply, &c->in.request_read);
struct reply_list *cur = malloc(sizeof(struct reply_list));
if(!cur)
return 0;
@@ -224,7 +224,7 @@ static int read_block(const int fd, void
void *XCBWaitForReply(XCBConnection *c, unsigned int request, XCBGenericError **e)
{
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
- XCBReplyData reader;
+ reader_list reader;
struct reply_list *head;
void *ret = 0;
if(e)
diff-tree 59621ada0c70041bd7625c0c21fa8a28d380b477 (from 5b307d328bdeb12f5f9f63d33095677a2c946049)
Author: Jamey Sharp <jamey at minilop.net>
Date: Mon Feb 27 00:54:59 2006 -0800
In struct XCBReplyData, change void *data to pthread_cond_t *data. That was dumb.
diff --git a/xcb/src/xcb_in.c b/xcb/src/xcb_in.c
index 76990f3..92bc0bf 100644
--- a/xcb/src/xcb_in.c
+++ b/xcb/src/xcb_in.c
@@ -55,7 +55,7 @@ typedef struct pending_reply {
typedef struct XCBReplyData {
unsigned int request;
- void *data;
+ pthread_cond_t *data;
} XCBReplyData;
static int match_reply(const void *request, const void *data)
diff-tree 5b307d328bdeb12f5f9f63d33095677a2c946049 (from 1ca041996d5347278a0c8fe4831b63b3fbdeda05)
Author: Jamey Sharp <jamey at minilop.net>
Date: Sun Feb 26 23:43:44 2006 -0800
Delete unused xcb_list functions and refactor others.
diff --git a/xcb/src/xcb_list.c b/xcb/src/xcb_list.c
index 6a72c16..718a380 100644
--- a/xcb/src/xcb_list.c
+++ b/xcb/src/xcb_list.c
@@ -53,35 +53,21 @@ _xcb_list *_xcb_list_new()
return list;
}
-static void _xcb_list_clear(_xcb_list *list, XCBListFreeFunc do_free)
-{
- void *tmp;
- while((tmp = _xcb_list_remove_head(list)))
- if(do_free)
- do_free(tmp);
-}
-
void _xcb_list_delete(_xcb_list *list, XCBListFreeFunc do_free)
{
if(!list)
return;
- _xcb_list_clear(list, do_free);
+ while(list->head)
+ {
+ node *cur = list->head;
+ if(do_free)
+ do_free(cur->data);
+ list->head = cur->next;
+ free(cur);
+ }
free(list);
}
-int _xcb_list_insert(_xcb_list *list, void *data)
-{
- node *cur;
- cur = malloc(sizeof(node));
- if(!cur)
- return 0;
- cur->data = data;
-
- cur->next = list->head;
- list->head = cur;
- return 1;
-}
-
int _xcb_list_append(_xcb_list *list, void *data)
{
node *cur;
@@ -103,20 +89,6 @@ void *_xcb_list_peek_head(_xcb_list *lis
return list->head->data;
}
-void *_xcb_list_remove_head(_xcb_list *list)
-{
- void *ret;
- node *tmp = list->head;
- if(!tmp)
- return 0;
- ret = tmp->data;
- list->head = tmp->next;
- if(!list->head)
- list->tail = &list->head;
- free(tmp);
- return ret;
-}
-
void *_xcb_list_remove(_xcb_list *list, int (*cmp)(const void *, const void *), const void *data)
{
node **cur;
@@ -153,14 +125,17 @@ _xcb_map *_xcb_map_new(void) __attribute
void _xcb_map_delete(_xcb_map *q, XCBListFreeFunc do_free)
{
- map_pair *tmp;
if(!q)
return;
- while((tmp = _xcb_list_remove_head(q)))
+ while(q->head)
{
+ node *cur = q->head;
+ map_pair *pair = cur->data;
if(do_free)
- do_free(tmp->value);
- free(tmp);
+ do_free(pair->value);
+ q->head = cur->next;
+ free(pair);
+ free(cur);
}
free(q);
}
@@ -185,14 +160,6 @@ static int match_map_pair(const void *ke
return ((map_pair *) pair)->key == *(unsigned int *) key;
}
-void *_xcb_map_get(_xcb_map *q, unsigned int key)
-{
- map_pair *cur = _xcb_list_find(q, match_map_pair, &key);
- if(!cur)
- return 0;
- return cur->value;
-}
-
void *_xcb_map_remove(_xcb_map *q, unsigned int key)
{
map_pair *cur = _xcb_list_remove(q, match_map_pair, &key);
diff --git a/xcb/src/xcbint.h b/xcb/src/xcbint.h
index c508504..85e79e3 100644
--- a/xcb/src/xcbint.h
+++ b/xcb/src/xcbint.h
@@ -46,10 +46,8 @@ typedef void (*XCBListFreeFunc)(void *);
_xcb_list *_xcb_list_new(void);
void _xcb_list_delete(_xcb_list *list, XCBListFreeFunc do_free);
-int _xcb_list_insert(_xcb_list *list, void *data);
int _xcb_list_append(_xcb_list *list, void *data);
void *_xcb_list_peek_head(_xcb_list *list);
-void *_xcb_list_remove_head(_xcb_list *list);
void *_xcb_list_remove(_xcb_list *list, int (*cmp)(const void *, const void *), const void *data);
void *_xcb_list_find(_xcb_list *list, int (*cmp)(const void *, const void *), const void *data);
@@ -58,7 +56,6 @@ typedef _xcb_list _xcb_map;
_xcb_map *_xcb_map_new(void);
void _xcb_map_delete(_xcb_map *q, XCBListFreeFunc do_free);
int _xcb_map_put(_xcb_map *q, unsigned int key, void *data);
-void *_xcb_map_get(_xcb_map *q, unsigned int key);
void *_xcb_map_remove(_xcb_map *q, unsigned int key);
diff-tree 1ca041996d5347278a0c8fe4831b63b3fbdeda05 (from dd2b82f9f9cf3deca1748e350da231a644c825d0)
Author: Jamey Sharp <jamey at minilop.net>
Date: Sun Feb 26 22:58:17 2006 -0800
Replace current_reply generic queue with hand-written version. No generic queues remain so delete their implementation.
diff --git a/xcb/src/xcb_in.c b/xcb/src/xcb_in.c
index cdaf558..76990f3 100644
--- a/xcb/src/xcb_in.c
+++ b/xcb/src/xcb_in.c
@@ -41,6 +41,11 @@ struct event_list {
struct event_list *next;
};
+struct reply_list {
+ void *reply;
+ struct reply_list *next;
+};
+
typedef struct pending_reply {
unsigned int request;
enum workarounds workaround;
@@ -99,10 +104,11 @@ static int read_packet(XCBConnection *c)
c->in.pending_replies_tail = &c->in.pending_replies;
free(oldpend);
}
- if(!_xcb_queue_is_empty(c->in.current_reply))
+ if(c->in.current_reply)
{
_xcb_map_put(c->in.replies, lastread, c->in.current_reply);
- c->in.current_reply = _xcb_queue_new();
+ c->in.current_reply = 0;
+ c->in.current_reply_tail = &c->in.current_reply;
}
}
if(c->in.request_read < lastread)
@@ -140,7 +146,13 @@ static int read_packet(XCBConnection *c)
if(genrep.response_type == 1 || (genrep.response_type == 0 && pend && (pend->flags & XCB_REQUEST_CHECKED)))
{
XCBReplyData *reader = _xcb_list_find(c->in.readers, match_reply, &c->in.request_read);
- _xcb_queue_enqueue(c->in.current_reply, buf);
+ struct reply_list *cur = malloc(sizeof(struct reply_list));
+ if(!cur)
+ return 0;
+ cur->reply = buf;
+ cur->next = 0;
+ *c->in.current_reply_tail = cur;
+ c->in.current_reply_tail = &cur->next;
if(reader)
pthread_cond_signal(reader->data);
return 1;
@@ -175,6 +187,17 @@ static XCBGenericEvent *get_event(XCBCon
return ret;
}
+static void free_reply_list(struct reply_list *head)
+{
+ while(head)
+ {
+ struct reply_list *cur = head;
+ head = cur->next;
+ free(cur->reply);
+ free(cur);
+ }
+}
+
static int read_block(const int fd, void *buf, const size_t len)
{
int done = 0;
@@ -202,6 +225,7 @@ void *XCBWaitForReply(XCBConnection *c,
{
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
XCBReplyData reader;
+ struct reply_list *head;
void *ret = 0;
if(e)
*e = 0;
@@ -222,31 +246,40 @@ void *XCBWaitForReply(XCBConnection *c,
/* If this request has not been read yet, wait for it. */
while(((signed int) (c->in.request_read - request) < 0 ||
- (c->in.request_read == request &&
- _xcb_queue_is_empty(c->in.current_reply))))
+ (c->in.request_read == request && !c->in.current_reply)))
if(!_xcb_conn_wait(c, /*should_write*/ 0, &cond))
goto done;
if(c->in.request_read != request)
{
- _xcb_queue *q = _xcb_map_get(c->in.replies, request);
- if(q)
+ head = _xcb_map_remove(c->in.replies, request);
+ if(head && head->next)
+ _xcb_map_put(c->in.replies, request, head->next);
+ }
+ else
+ {
+ head = c->in.current_reply;
+ if(head)
{
- ret = _xcb_queue_dequeue(q);
- if(_xcb_queue_is_empty(q))
- _xcb_queue_delete(_xcb_map_remove(c->in.replies, request), free);
+ c->in.current_reply = head->next;
+ if(!head->next)
+ c->in.current_reply_tail = &c->in.current_reply;
}
}
- else
- ret = _xcb_queue_dequeue(c->in.current_reply);
- if(ret && ((XCBGenericRep *) ret)->response_type == 0) /* X error */
+ if(head)
{
- if(e)
- *e = ret;
- else
- free(ret);
- ret = 0;
+ ret = head->reply;
+ free(head);
+
+ if(((XCBGenericRep *) ret)->response_type == 0) /* X error */
+ {
+ if(e)
+ *e = ret;
+ else
+ free(ret);
+ ret = 0;
+ }
}
done:
@@ -319,13 +352,13 @@ int _xcb_in_init(_xcb_in *in)
in->queue_len = 0;
in->request_read = 0;
- in->current_reply = _xcb_queue_new();
in->replies = _xcb_map_new();
in->readers = _xcb_list_new();
- if(!in->current_reply || !in->replies || !in->readers)
+ if(!in->replies || !in->readers)
return 0;
+ in->current_reply_tail = &in->current_reply;
in->events_tail = &in->events;
in->pending_replies_tail = &in->pending_replies;
@@ -335,8 +368,8 @@ int _xcb_in_init(_xcb_in *in)
void _xcb_in_destroy(_xcb_in *in)
{
pthread_cond_destroy(&in->event_cond);
- _xcb_queue_delete(in->current_reply, free);
- _xcb_map_delete(in->replies, free);
+ free_reply_list(in->current_reply);
+ _xcb_map_delete(in->replies, (void (*)(void *)) free_reply_list);
_xcb_list_delete(in->readers, 0);
while(in->events)
{
diff --git a/xcb/src/xcb_list.c b/xcb/src/xcb_list.c
index 5b2edc0..6a72c16 100644
--- a/xcb/src/xcb_list.c
+++ b/xcb/src/xcb_list.c
@@ -144,16 +144,6 @@ void *_xcb_list_find(_xcb_list *list, in
return 0;
}
-_xcb_queue *_xcb_queue_new(void) __attribute__ ((alias ("_xcb_list_new")));
-void _xcb_queue_delete(_xcb_queue *q, XCBListFreeFunc do_free) __attribute__ ((alias ("_xcb_list_delete")));
-int _xcb_queue_enqueue(_xcb_queue *q, void *data) __attribute__ ((alias ("_xcb_list_append")));
-void *_xcb_queue_dequeue(_xcb_queue *q) __attribute__ ((alias ("_xcb_list_remove_head")));
-
-int _xcb_queue_is_empty(_xcb_queue *q)
-{
- return q->head == 0;
-}
-
typedef struct {
unsigned int key;
void *value;
diff --git a/xcb/src/xcbint.h b/xcb/src/xcbint.h
index 6a61d18..c508504 100644
--- a/xcb/src/xcbint.h
+++ b/xcb/src/xcbint.h
@@ -53,14 +53,6 @@ void *_xcb_list_remove_head(_xcb_list *l
void *_xcb_list_remove(_xcb_list *list, int (*cmp)(const void *, const void *), const void *data);
void *_xcb_list_find(_xcb_list *list, int (*cmp)(const void *, const void *), const void *data);
-typedef _xcb_list _xcb_queue;
-
-_xcb_queue *_xcb_queue_new(void);
-void _xcb_queue_delete(_xcb_queue *q, XCBListFreeFunc do_free);
-int _xcb_queue_enqueue(_xcb_queue *q, void *data);
-void *_xcb_queue_dequeue(_xcb_queue *q);
-int _xcb_queue_is_empty(_xcb_queue *q);
-
typedef _xcb_list _xcb_map;
_xcb_map *_xcb_map_new(void);
@@ -106,7 +98,8 @@ typedef struct _xcb_in {
int queue_len;
unsigned int request_read;
- _xcb_queue *current_reply;
+ struct reply_list *current_reply;
+ struct reply_list **current_reply_tail;
_xcb_map *replies;
struct event_list *events;
diff-tree dd2b82f9f9cf3deca1748e350da231a644c825d0 (from 8545ecb2f1f8649753c5ce038f6aa1fd865dcfc6)
Author: Jamey Sharp <jamey at minilop.net>
Date: Sun Feb 26 18:28:50 2006 -0800
Replace events generic queue with hand-written typesafe version.
diff --git a/xcb/src/xcb_in.c b/xcb/src/xcb_in.c
index 1f6dcbe..cdaf558 100644
--- a/xcb/src/xcb_in.c
+++ b/xcb/src/xcb_in.c
@@ -36,6 +36,11 @@
#include "xcbext.h"
#include "xcbint.h"
+struct event_list {
+ XCBGenericEvent *event;
+ struct event_list *next;
+};
+
typedef struct pending_reply {
unsigned int request;
enum workarounds workaround;
@@ -68,8 +73,9 @@ static int read_packet(XCBConnection *c)
{
XCBGenericRep genrep;
int length = 32;
- unsigned char *buf;
+ void *buf;
pending_reply *pend = 0;
+ struct event_list *event;
/* Wait for there to be enough data for us to read a whole packet */
if(c->in.queue_len < length)
@@ -141,11 +147,34 @@ static int read_packet(XCBConnection *c)
}
/* event, or unchecked error */
- _xcb_queue_enqueue(c->in.events, buf);
+ event = malloc(sizeof(struct event_list));
+ if(!event)
+ {
+ free(buf);
+ return 0;
+ }
+ event->event = buf;
+ event->next = 0;
+ *c->in.events_tail = event;
+ c->in.events_tail = &event->next;
pthread_cond_signal(&c->in.event_cond);
return 1; /* I have something for you... */
}
+static XCBGenericEvent *get_event(XCBConnection *c)
+{
+ struct event_list *cur = c->in.events;
+ XCBGenericEvent *ret;
+ if(!c->in.events)
+ return 0;
+ ret = cur->event;
+ c->in.events = cur->next;
+ if(!cur->next)
+ c->in.events_tail = &c->in.events;
+ free(cur);
+ return ret;
+}
+
static int read_block(const int fd, void *buf, const size_t len)
{
int done = 0;
@@ -238,8 +267,8 @@ XCBGenericEvent *XCBWaitForEvent(XCBConn
{
XCBGenericEvent *ret;
pthread_mutex_lock(&c->iolock);
- /* _xcb_list_remove_head returns 0 on empty list. */
- while(!(ret = _xcb_queue_dequeue(c->in.events)))
+ /* get_event returns 0 on empty list. */
+ while(!(ret = get_event(c)))
if(!_xcb_conn_wait(c, /*should_write*/ 0, &c->in.event_cond))
break;
@@ -256,7 +285,7 @@ XCBGenericEvent *XCBPollForEvent(XCBConn
*error = 0;
/* FIXME: follow X meets Z architecture changes. */
if(_xcb_in_read(c))
- ret = _xcb_queue_dequeue(c->in.events);
+ ret = get_event(c);
else if(error)
*error = -1;
else
@@ -293,11 +322,11 @@ int _xcb_in_init(_xcb_in *in)
in->current_reply = _xcb_queue_new();
in->replies = _xcb_map_new();
- in->events = _xcb_queue_new();
in->readers = _xcb_list_new();
- if(!in->current_reply || !in->replies || !in->events || !in->readers)
+ if(!in->current_reply || !in->replies || !in->readers)
return 0;
+ in->events_tail = &in->events;
in->pending_replies_tail = &in->pending_replies;
return 1;
@@ -308,8 +337,14 @@ void _xcb_in_destroy(_xcb_in *in)
pthread_cond_destroy(&in->event_cond);
_xcb_queue_delete(in->current_reply, free);
_xcb_map_delete(in->replies, free);
- _xcb_queue_delete(in->events, free);
_xcb_list_delete(in->readers, 0);
+ while(in->events)
+ {
+ struct event_list *e = in->events;
+ in->events = e->next;
+ free(e->event);
+ free(e);
+ }
while(in->pending_replies)
{
pending_reply *pend = in->pending_replies;
diff --git a/xcb/src/xcbint.h b/xcb/src/xcbint.h
index 670dd69..6a61d18 100644
--- a/xcb/src/xcbint.h
+++ b/xcb/src/xcbint.h
@@ -109,7 +109,8 @@ typedef struct _xcb_in {
_xcb_queue *current_reply;
_xcb_map *replies;
- _xcb_queue *events;
+ struct event_list *events;
+ struct event_list **events_tail;
_xcb_list *readers;
struct pending_reply *pending_replies;
diff-tree 8545ecb2f1f8649753c5ce038f6aa1fd865dcfc6 (from 804a716f0c606622e10cfc8286af4b67434db1d8)
Author: Jamey Sharp <jamey at minilop.net>
Date: Sun Feb 26 15:45:08 2006 -0800
API/ABI break: Add flags to XCBSendRequest, first for error-checked requests.
There's no more race condition between event and reply handling.
The *RequestBlind and *RequestChecked functions are not yet implemented.
diff --git a/xcb/src/c-client.xsl b/xcb/src/c-client.xsl
index 903895d..3ab2889 100644
--- a/xcb/src/c-client.xsl
+++ b/xcb/src/c-client.xsl
@@ -611,7 +611,11 @@ authorization from the authors.
</xsl:if>;</l>
</xsl:for-each>
- <l>XCBSendRequest(c, &xcb_ret.sequence, xcb_parts, &xcb_req);</l>
+ <l>XCBSendRequest(c, &xcb_ret.sequence, <!--
+ --><xsl:choose>
+ <xsl:when test="@has-reply">XCB_REQUEST_CHECKED</xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>, xcb_parts, &xcb_req);</l>
<l>return xcb_ret;</l>
</xsl:template>
diff --git a/xcb/src/xcb_in.c b/xcb/src/xcb_in.c
index e050dfc..1f6dcbe 100644
--- a/xcb/src/xcb_in.c
+++ b/xcb/src/xcb_in.c
@@ -39,21 +39,15 @@
typedef struct pending_reply {
unsigned int request;
enum workarounds workaround;
+ int flags;
struct pending_reply *next;
} pending_reply;
typedef struct XCBReplyData {
unsigned int request;
void *data;
- XCBGenericError **error;
} XCBReplyData;
-static int match_request_error(const void *request, const void *data)
-{
- const XCBGenericError *e = data;
- return e->response_type == 0 && e->sequence == ((*(unsigned int *) request) & 0xffff);
-}
-
static int match_reply(const void *request, const void *data)
{
return ((XCBReplyData *) data)->request == *(unsigned int *) request;
@@ -75,6 +69,7 @@ static int read_packet(XCBConnection *c)
XCBGenericRep genrep;
int length = 32;
unsigned char *buf;
+ pending_reply *pend = 0;
/* Wait for there to be enough data for us to read a whole packet */
if(c->in.queue_len < length)
@@ -88,36 +83,40 @@ static int read_packet(XCBConnection *c)
{
int lastread = c->in.request_read;
c->in.request_read = (lastread & 0xffff0000) | genrep.sequence;
- if(c->in.request_read != lastread && !_xcb_queue_is_empty(c->in.current_reply))
+ if(c->in.request_read != lastread)
{
- _xcb_map_put(c->in.replies, lastread, c->in.current_reply);
- c->in.current_reply = _xcb_queue_new();
+ pending_reply *oldpend = c->in.pending_replies;
+ if(oldpend && oldpend->request == lastread)
+ {
+ c->in.pending_replies = oldpend->next;
+ if(!oldpend->next)
+ c->in.pending_replies_tail = &c->in.pending_replies;
+ free(oldpend);
+ }
+ if(!_xcb_queue_is_empty(c->in.current_reply))
+ {
+ _xcb_map_put(c->in.replies, lastread, c->in.current_reply);
+ c->in.current_reply = _xcb_queue_new();
+ }
}
if(c->in.request_read < lastread)
c->in.request_read += 0x10000;
}
+ if(genrep.response_type == 0 || genrep.response_type == 1)
+ {
+ pend = c->in.pending_replies;
+ if(pend && pend->request != c->in.request_read)
+ pend = 0;
+ }
+
/* For reply packets, check that the entire packet is available. */
if(genrep.response_type == 1)
{
- pending_reply *pend = c->in.pending_replies;
- if(pend && pend->request == c->in.request_read)
+ if(pend && pend->workaround == WORKAROUND_GLX_GET_FB_CONFIGS_BUG)
{
- switch(pend->workaround)
- {
- case WORKAROUND_NONE:
- break;
- case WORKAROUND_GLX_GET_FB_CONFIGS_BUG:
- {
- CARD32 *p = (CARD32 *) c->in.queue;
- genrep.length = p[2] * p[3] * 2;
- }
- break;
- }
- c->in.pending_replies = pend->next;
- if(!pend->next)
- c->in.pending_replies_tail = &c->in.pending_replies;
- free(pend);
+ CARD32 *p = (CARD32 *) c->in.queue;
+ genrep.length = p[2] * p[3] * 2;
}
length += genrep.length * 4;
}
@@ -131,7 +130,8 @@ static int read_packet(XCBConnection *c)
return 0;
}
- if(buf[0] == 1) /* response is a reply */
+ /* reply, or checked error */
+ if(genrep.response_type == 1 || (genrep.response_type == 0 && pend && (pend->flags & XCB_REQUEST_CHECKED)))
{
XCBReplyData *reader = _xcb_list_find(c->in.readers, match_reply, &c->in.request_read);
_xcb_queue_enqueue(c->in.current_reply, buf);
@@ -140,18 +140,7 @@ static int read_packet(XCBConnection *c)
return 1;
}
- if(buf[0] == 0) /* response is an error */
- {
- XCBReplyData *reader = _xcb_list_find(c->in.readers, match_reply, &c->in.request_read);
- if(reader && reader->error)
- {
- *reader->error = (XCBGenericError *) buf;
- pthread_cond_signal(reader->data);
- return 1;
- }
- }
-
- /* event, or error without a waiting reader */
+ /* event, or unchecked error */
_xcb_queue_enqueue(c->in.events, buf);
pthread_cond_signal(&c->in.event_cond);
return 1; /* I have something for you... */
@@ -198,20 +187,12 @@ void *XCBWaitForReply(XCBConnection *c,
if(_xcb_list_find(c->in.readers, match_reply, &request))
goto done; /* error */
- if(e)
- {
- *e = _xcb_list_remove(c->in.events, match_request_error, &request);
- if(*e)
- goto done;
- }
-
reader.request = request;
reader.data = &cond;
- reader.error = e;
_xcb_list_append(c->in.readers, &reader);
/* If this request has not been read yet, wait for it. */
- while(!(e && *e) && ((signed int) (c->in.request_read - request) < 0 ||
+ while(((signed int) (c->in.request_read - request) < 0 ||
(c->in.request_read == request &&
_xcb_queue_is_empty(c->in.current_reply))))
if(!_xcb_conn_wait(c, /*should_write*/ 0, &cond))
@@ -230,6 +211,15 @@ void *XCBWaitForReply(XCBConnection *c,
else
ret = _xcb_queue_dequeue(c->in.current_reply);
+ if(ret && ((XCBGenericRep *) ret)->response_type == 0) /* X error */
+ {
+ if(e)
+ *e = ret;
+ else
+ free(ret);
+ ret = 0;
+ }
+
done:
_xcb_list_remove(c->in.readers, match_reply, &request);
pthread_cond_destroy(&cond);
@@ -328,15 +318,16 @@ void _xcb_in_destroy(_xcb_in *in)
}
}
-int _xcb_in_expect_reply(XCBConnection *c, unsigned int request, enum workarounds workaround)
+int _xcb_in_expect_reply(XCBConnection *c, unsigned int request, enum workarounds workaround, int flags)
{
- if(workaround != WORKAROUND_NONE)
+ if(workaround != WORKAROUND_NONE || flags != 0)
{
pending_reply *pend = malloc(sizeof(pending_reply));
if(!pend)
return 0;
pend->request = request;
pend->workaround = workaround;
+ pend->flags = flags;
pend->next = 0;
*c->in.pending_replies_tail = pend;
c->in.pending_replies_tail = &pend->next;
diff --git a/xcb/src/xcb_out.c b/xcb/src/xcb_out.c
index fd0a27f..8eb8a7a 100644
--- a/xcb/src/xcb_out.c
+++ b/xcb/src/xcb_out.c
@@ -79,7 +79,7 @@ CARD32 XCBGetMaximumRequestLength(XCBCon
return c->out.maximum_request_length;
}
-int XCBSendRequest(XCBConnection *c, unsigned int *request, struct iovec *vector, const XCBProtocolRequest *req)
+int XCBSendRequest(XCBConnection *c, unsigned int *request, int flags, struct iovec *vector, const XCBProtocolRequest *req)
{
static const char pad[3];
int ret;
@@ -105,7 +105,7 @@ int XCBSendRequest(XCBConnection *c, uns
((CARD8 *) vector[0].iov_base)[1] = req->opcode;
/* do we need to work around the X server bug described in glx.xml? */
- if(strcmp(req->ext->name, "GLX") &&
+ if(!req->isvoid && strcmp(req->ext->name, "GLX") &&
((req->opcode == 17 && ((CARD32 *) vector[0].iov_base)[0] == 0x10004) ||
req->opcode == 21))
workaround = WORKAROUND_GLX_GET_FB_CONFIGS_BUG;
@@ -172,8 +172,7 @@ int XCBSendRequest(XCBConnection *c, uns
*request = ++c->out.request;
- if(!req->isvoid)
- _xcb_in_expect_reply(c, *request, workaround);
+ _xcb_in_expect_reply(c, *request, workaround, flags);
ret = _xcb_out_write_block(c, padded, padlen);
pthread_mutex_unlock(&c->iolock);
diff --git a/xcb/src/xcbext.h b/xcb/src/xcbext.h
index c8f532c..ddbb77a 100644
--- a/xcb/src/xcbext.h
+++ b/xcb/src/xcbext.h
@@ -51,7 +51,11 @@ typedef struct {
BOOL isvoid;
} XCBProtocolRequest;
-int XCBSendRequest(XCBConnection *c, unsigned int *sequence, struct iovec *vector, const XCBProtocolRequest *request);
+enum XCBSendRequestFlags {
+ XCB_REQUEST_CHECKED = 1 << 0
+};
+
+int XCBSendRequest(XCBConnection *c, unsigned int *sequence, int flags, struct iovec *vector, const XCBProtocolRequest *request);
/* xcb_in.c */
diff --git a/xcb/src/xcbint.h b/xcb/src/xcbint.h
index eb1afc1..670dd69 100644
--- a/xcb/src/xcbint.h
+++ b/xcb/src/xcbint.h
@@ -119,7 +119,7 @@ typedef struct _xcb_in {
int _xcb_in_init(_xcb_in *in);
void _xcb_in_destroy(_xcb_in *in);
-int _xcb_in_expect_reply(XCBConnection *c, unsigned int request, enum workarounds workaround);
+int _xcb_in_expect_reply(XCBConnection *c, unsigned int request, enum workarounds workaround, int flags);
int _xcb_in_read(XCBConnection *c);
int _xcb_in_read_block(XCBConnection *c, void *buf, int nread);
diff-tree 804a716f0c606622e10cfc8286af4b67434db1d8 (from 121e6fe8f1754ee2b1306ee747a8132ae9aa5da7)
Author: Jamey Sharp <jamey at minilop.net>
Date: Sun Feb 26 02:00:03 2006 -0800
Replace pending_replies generic queue with a hand-implemented typesafe version.
diff --git a/xcb/src/xcb_in.c b/xcb/src/xcb_in.c
index 6f084ba..e050dfc 100644
--- a/xcb/src/xcb_in.c
+++ b/xcb/src/xcb_in.c
@@ -36,9 +36,10 @@
#include "xcbext.h"
#include "xcbint.h"
-typedef struct {
+typedef struct pending_reply {
unsigned int request;
enum workarounds workaround;
+ struct pending_reply *next;
} pending_reply;
typedef struct XCBReplyData {
@@ -99,7 +100,7 @@ static int read_packet(XCBConnection *c)
/* For reply packets, check that the entire packet is available. */
if(genrep.response_type == 1)
{
- pending_reply *pend = _xcb_list_peek_head(c->in.pending_replies);
+ pending_reply *pend = c->in.pending_replies;
if(pend && pend->request == c->in.request_read)
{
switch(pend->workaround)
@@ -113,7 +114,10 @@ static int read_packet(XCBConnection *c)
}
break;
}
- free(_xcb_queue_dequeue(c->in.pending_replies));
+ c->in.pending_replies = pend->next;
+ if(!pend->next)
+ c->in.pending_replies_tail = &c->in.pending_replies;
+ free(pend);
}
length += genrep.length * 4;
}
@@ -301,11 +305,11 @@ int _xcb_in_init(_xcb_in *in)
in->replies = _xcb_map_new();
in->events = _xcb_queue_new();
in->readers = _xcb_list_new();
-
- in->pending_replies = _xcb_queue_new();
- if(!in->current_reply || !in->replies || !in->events || !in->readers || !in->pending_replies)
+ if(!in->current_reply || !in->replies || !in->events || !in->readers)
return 0;
+ in->pending_replies_tail = &in->pending_replies;
+
return 1;
}
@@ -316,7 +320,12 @@ void _xcb_in_destroy(_xcb_in *in)
_xcb_map_delete(in->replies, free);
_xcb_queue_delete(in->events, free);
_xcb_list_delete(in->readers, 0);
- _xcb_queue_delete(in->pending_replies, free);
+ while(in->pending_replies)
+ {
+ pending_reply *pend = in->pending_replies;
+ in->pending_replies = pend->next;
+ free(pend);
+ }
}
int _xcb_in_expect_reply(XCBConnection *c, unsigned int request, enum workarounds workaround)
@@ -328,11 +337,9 @@ int _xcb_in_expect_reply(XCBConnection *
return 0;
pend->request = request;
pend->workaround = workaround;
- if(!_xcb_queue_enqueue(c->in.pending_replies, pend))
- {
- free(pend);
- return 0;
- }
+ pend->next = 0;
+ *c->in.pending_replies_tail = pend;
+ c->in.pending_replies_tail = &pend->next;
}
return 1;
}
diff --git a/xcb/src/xcbint.h b/xcb/src/xcbint.h
index e8e98eb..eb1afc1 100644
--- a/xcb/src/xcbint.h
+++ b/xcb/src/xcbint.h
@@ -112,7 +112,8 @@ typedef struct _xcb_in {
_xcb_queue *events;
_xcb_list *readers;
- _xcb_queue *pending_replies;
+ struct pending_reply *pending_replies;
+ struct pending_reply **pending_replies_tail;
} _xcb_in;
int _xcb_in_init(_xcb_in *in);
diff-tree 121e6fe8f1754ee2b1306ee747a8132ae9aa5da7 (from f1d1fbea2d96fee193b28721d173a3787708daca)
Author: Jamey Sharp <jamey at minilop.net>
Date: Sun Feb 26 01:27:01 2006 -0800
Replace my old generic map ADT with a growable array for the extension cache.
diff --git a/xcb/src/xcb_ext.c b/xcb/src/xcb_ext.c
index 46a5519..610ec57 100644
--- a/xcb/src/xcb_ext.c
+++ b/xcb/src/xcb_ext.c
@@ -32,14 +32,29 @@
#include "xcbext.h"
#include "xcbint.h"
-typedef struct {
- enum { LAZY_COOKIE, LAZY_FORCED } tag;
+typedef struct lazyreply {
+ enum { LAZY_NONE = 0, LAZY_COOKIE, LAZY_FORCED } tag;
union {
XCBQueryExtensionCookie cookie;
XCBQueryExtensionRep *reply;
} value;
} lazyreply;
+static lazyreply *get_index(XCBConnection *c, int index)
+{
+ if(index > c->ext.extensions_size)
+ {
+ int new_size = index << 1;
+ lazyreply *new_extensions = realloc(c->ext.extensions, sizeof(lazyreply) * new_size);
+ if(!new_extensions)
+ return 0;
+ memset(new_extensions + c->ext.extensions_size, 0, sizeof(lazyreply) * (new_size - c->ext.extensions_size));
+ c->ext.extensions = new_extensions;
+ c->ext.extensions_size = new_size;
+ }
+ return c->ext.extensions + index - 1;
+}
+
static lazyreply *get_lazyreply(XCBConnection *c, XCBExtension *ext)
{
static pthread_mutex_t global_lock = PTHREAD_MUTEX_INITIALIZER;
@@ -52,28 +67,16 @@ static lazyreply *get_lazyreply(XCBConne
ext->global_id = ++next_global_id;
pthread_mutex_unlock(&global_lock);
- data = _xcb_map_get(c->ext.extensions, ext->global_id);
- if(!data)
+ data = get_index(c, ext->global_id);
+ if(data && data->tag == LAZY_NONE)
{
/* cache miss: query the server */
- data = malloc(sizeof(lazyreply));
- if(!data)
- return 0;
data->tag = LAZY_COOKIE;
data->value.cookie = XCBQueryExtension(c, strlen(ext->name), ext->name);
- _xcb_map_put(c->ext.extensions, ext->global_id, data);
}
return data;
}
-static void free_lazyreply(void *p)
-{
- lazyreply *data = p;
- if(data->tag == LAZY_FORCED)
- free(data->value.reply);
- free(data);
-}
-
/* Public interface */
/* Do not free the returned XCBQueryExtensionRep - on return, it's aliased
@@ -107,16 +110,14 @@ int _xcb_ext_init(XCBConnection *c)
{
if(pthread_mutex_init(&c->ext.lock, 0))
return 0;
-
- c->ext.extensions = _xcb_map_new();
- if(!c->ext.extensions)
- return 0;
-
return 1;
}
void _xcb_ext_destroy(XCBConnection *c)
{
pthread_mutex_destroy(&c->ext.lock);
- _xcb_map_delete(c->ext.extensions, free_lazyreply);
+ while(c->ext.extensions_size-- > 0)
+ if(c->ext.extensions[c->ext.extensions_size].tag == LAZY_FORCED)
+ free(c->ext.extensions[c->ext.extensions_size].value.reply);
+ free(c->ext.extensions);
}
diff --git a/xcb/src/xcbint.h b/xcb/src/xcbint.h
index 34b7197..e8e98eb 100644
--- a/xcb/src/xcbint.h
+++ b/xcb/src/xcbint.h
@@ -142,7 +142,8 @@ void _xcb_xid_destroy(XCBConnection *c);
typedef struct _xcb_ext {
pthread_mutex_t lock;
- _xcb_map *extensions;
+ struct lazyreply *extensions;
+ int extensions_size;
} _xcb_ext;
int _xcb_ext_init(XCBConnection *c);
diff-tree f1d1fbea2d96fee193b28721d173a3787708daca (from 71bda5a7381aff8d40d13e1f140342f310a82b33)
Author: Jamey Sharp <jamey at minilop.net>
Date: Sat Feb 25 23:27:47 2006 -0800
XCB has not had tracing features for a long time: remove the remnants.
diff --git a/xcb/src/xcb_in.c b/xcb/src/xcb_in.c
index dc12fa2..6f084ba 100644
--- a/xcb/src/xcb_in.c
+++ b/xcb/src/xcb_in.c
@@ -243,11 +243,6 @@ XCBGenericEvent *XCBWaitEvent(XCBConnect
XCBGenericEvent *XCBWaitForEvent(XCBConnection *c)
{
XCBGenericEvent *ret;
-
-#if XCBTRACEEVENT
- fprintf(stderr, "Entering XCBWaitEvent\n");
-#endif
-
pthread_mutex_lock(&c->iolock);
/* _xcb_list_remove_head returns 0 on empty list. */
while(!(ret = _xcb_queue_dequeue(c->in.events)))
@@ -256,11 +251,6 @@ XCBGenericEvent *XCBWaitForEvent(XCBConn
wake_up_next_reader(c);
pthread_mutex_unlock(&c->iolock);
-
-#if XCBTRACEEVENT
- fprintf(stderr, "Leaving XCBWaitEvent, event type %d\n", ret ? ret->response_type : -1);
-#endif
-
return ret;
}
diff-tree 71bda5a7381aff8d40d13e1f140342f310a82b33 (from 6437d3696868cf453e0d892be959afe41111c037)
Author: Jamey Sharp <jamey at minilop.net>
Date: Sat Feb 25 23:26:55 2006 -0800
Rearrange an if statement that's been bothering me.
diff --git a/xcb/src/xcb_out.c b/xcb/src/xcb_out.c
index 145bddd..fd0a27f 100644
--- a/xcb/src/xcb_out.c
+++ b/xcb/src/xcb_out.c
@@ -117,17 +117,14 @@ int XCBSendRequest(XCBConnection *c, uns
for(i = 0; i < req->count; ++i)
longlen += (vector[i].iov_len + 3) >> 2;
- if(longlen > c->setup->maximum_request_length)
- {
- if(longlen > XCBGetMaximumRequestLength(c))
- return 0; /* server can't take this; maybe need BIGREQUESTS? */
- }
- else
+ if(longlen <= c->setup->maximum_request_length)
{
/* we don't need BIGREQUESTS. */
shortlen = longlen;
longlen = 0;
}
+ else if(longlen > XCBGetMaximumRequestLength(c))
+ return 0; /* server can't take this; maybe need BIGREQUESTS? */
padded =
#ifdef HAVE_ALLOCA
More information about the xcb-commit
mailing list