[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 &amp; 3;</l>
     </xsl:for-each>
 
-    <l>XCBSendRequest(c, &amp;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 = &amp;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 &amp; 3;</l>
+    <l>xcb_parts[2].iov_base = &amp;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 &amp; 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 &amp; 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 &amp; 3;</l>
     </xsl:for-each>
 
     <l>XCBSendRequest(c, &amp;xcb_ret.sequence, <!--
     --><xsl:choose>
          <xsl:when test="@has-reply">XCB_REQUEST_CHECKED</xsl:when>
          <xsl:otherwise>0</xsl:otherwise>
-       </xsl:choose>, xcb_parts, &amp;xcb_req);</l>
+       </xsl:choose>, xcb_parts + 2, &amp;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 &amp; 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 &amp; 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 &amp; 3;</l>
     </xsl:for-each>
 
     <l>XCBSendRequest(c, &amp;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 = &amp;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 &amp; 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 &amp; 3;</l>
     </xsl:for-each>
 
     <l>XCBSendRequest(c, &amp;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, &amp;xcb_ret.sequence, xcb_parts, &amp;xcb_req);</l>
+    <l>XCBSendRequest(c, &amp;xcb_ret.sequence, <!--
+    --><xsl:choose>
+         <xsl:when test="@has-reply">XCB_REQUEST_CHECKED</xsl:when>
+         <xsl:otherwise>0</xsl:otherwise>
+       </xsl:choose>, xcb_parts, &amp;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