Author: brane
Date: Wed Aug  6 12:02:37 2025
New Revision: 1927641

Log:
On the SERF-195 branch: apply the patch from the issue tracker, with some
tweaks (no abort() calls in production code, use a static initializer).

* serf_private.h
  (serf_reqlist_t): New. Linked list of requests.
  (serf_request_t): Add a member serf_reqlist_t *next.
  (serf_connection_t): Change the three reqest lists to serf_reqlist_t.
  (serf__link_requests,
   serf__req_list_length): Remove prototypes.
  (serf__push_request,
   serf__peek_request,
   serf__take_request,
   serf__delete_from_reqlist,
   serf__cancel_request,
   serf__req_list_recalc_length): New and modified prototypes.

* src/outgoing_request.c
  (SERF__REQLIST_assert): New debug-assert macro.
  (serf__link_requests): Removed.
  ((serf__push_request,
   serf__peek_request,
   serf__take_request,
   serf__delete_from_reqlist): New.
  (serf__cancel_request): Change the 'list' argument type and update.
  (serf__destroy_request,
   serf__provide_credentials,
   create_request,
   serf_connection_request_create,
   insert_priority_request,
   serf_connection__request_requeue): Use serf_reqlist_t members and functions.

* src/outgoing.c
  (reqlist_null): New, static initializer for serf_reqlist_t.
  (serf_connection_create): Initialize lists with reqlist_null.

  (request_pending,
   serf__conn_update_pollset,
   check_buckets_drained,
   serf__connection_pre_cleanup,
   serf_connection__perform_setup,
   reset_connection,
   request_writing_finished,
   read_from_connection,
   serf_connection_close,
   serf_connection_queued_requests,
   serf_connection_pending_requests): Use serf_reqlist_t members and functions.

* protocols/http2_protocol.c
  (http2_outgoing_write): Use serf_reqlist_t members.
* protocols/http2_stream.c
  (serf_http2__stream_setup_next_request,
   serf_http2__stream_processor): Use serf_reqlist_t members and functions.

Modified:
   serf/branches/SERF-195/protocols/http2_protocol.c
   serf/branches/SERF-195/protocols/http2_stream.c
   serf/branches/SERF-195/serf_private.h
   serf/branches/SERF-195/src/outgoing.c
   serf/branches/SERF-195/src/outgoing_request.c

Modified: serf/branches/SERF-195/protocols/http2_protocol.c
==============================================================================
--- serf/branches/SERF-195/protocols/http2_protocol.c   Wed Aug  6 10:55:54 
2025        (r1927640)
+++ serf/branches/SERF-195/protocols/http2_protocol.c   Wed Aug  6 12:02:37 
2025        (r1927641)
@@ -1698,8 +1698,8 @@ http2_outgoing_write(serf_connection_t *
     serf_http2_protocol_t *h2 = conn->protocol_baton;
     apr_status_t status;
 
-    if (conn->unwritten_reqs
-        && conn->nr_of_written_reqs < h2->lr_max_concurrent)
+    if (conn->unwritten_reqs.head
+        && conn->written_reqs.count < h2->lr_max_concurrent)
     {
         status = enqueue_http2_request(h2);
         if (status)

Modified: serf/branches/SERF-195/protocols/http2_stream.c
==============================================================================
--- serf/branches/SERF-195/protocols/http2_stream.c     Wed Aug  6 10:55:54 
2025        (r1927640)
+++ serf/branches/SERF-195/protocols/http2_stream.c     Wed Aug  6 12:02:37 
2025        (r1927641)
@@ -339,7 +339,7 @@ serf_http2__stream_setup_next_request(se
                                       apr_size_t max_payload_size,
                                       serf_hpack_table_t *hpack_tbl)
 {
-    serf_request_t *request = conn->unwritten_reqs;
+    serf_request_t *request = conn->unwritten_reqs.head;
     apr_status_t status;
     serf_bucket_t *hpack;
     serf_bucket_t *body;
@@ -359,16 +359,8 @@ serf_http2__stream_setup_next_request(se
             return status;
     }
 
-    conn->unwritten_reqs = request->next;
-    if (conn->unwritten_reqs_tail == request)
-        conn->unwritten_reqs = conn->unwritten_reqs_tail = NULL;
-
-    request->next = NULL;
-
-    serf__link_requests(&conn->written_reqs, &conn->written_reqs_tail,
-                        request);
-    conn->nr_of_written_reqs++;
-    conn->nr_of_unwritten_reqs--;
+    serf__take_request(&conn->unwritten_reqs, request);
+    serf__push_request(&conn->written_reqs, request);
 
     serf__bucket_request_read(request->req_bkt, &body, NULL, NULL);
     status = serf__bucket_hpack_create_from_request(
@@ -802,24 +794,7 @@ serf_http2__stream_processor(void *baton
              to remove it from the outstanding requests */
         {
             serf_connection_t *conn = serf_request_get_conn(sd->request);
-            serf_request_t **rq = &conn->written_reqs;
-            serf_request_t *last = NULL;
-
-            while (*rq && (*rq != sd->request)) {
-                last = *rq;
-                rq = &last->next;
-            }
-
-            if (*rq)
-            {
-                (*rq) = sd->request->next;
-
-                if (conn->written_reqs_tail == sd->request)
-                    conn->written_reqs_tail = last;
-
-                conn->nr_of_written_reqs--;
-            }
-
+            serf__delete_from_reqlist(&conn->written_reqs, sd->request);
             serf__destroy_request(sd->request);
             stream->data->request = NULL;
         }

Modified: serf/branches/SERF-195/serf_private.h
==============================================================================
--- serf/branches/SERF-195/serf_private.h       Wed Aug  6 10:55:54 2025        
(r1927640)
+++ serf/branches/SERF-195/serf_private.h       Wed Aug  6 12:02:37 2025        
(r1927641)
@@ -262,6 +262,12 @@ typedef enum serf_request_writing_t {
     SERF_WRITING_FINISHED       /* Safe to destroy */
 } serf_request_writing_t;
 
+typedef struct serf_reqlist_t {
+    struct serf_request_t *head;
+    struct serf_request_t *tail;
+    unsigned int count;
+} serf_reqlist_t;
+
 /* Holds all the information corresponding to a request/response pair. */
 struct serf_request_t {
     serf_connection_t *conn;
@@ -307,7 +313,8 @@ struct serf_request_t {
        for identifying or storing related information */
     void *protocol_baton;
 
-    struct serf_request_t *next;
+    serf_request_t *next;
+    serf_reqlist_t *list;
 };
 
 struct serf_incoming_request_t
@@ -594,20 +601,15 @@ struct serf_connection_t {
 
     /* The list of requests that are written but no response has been received
        yet. */
-    serf_request_t *written_reqs;
-    serf_request_t *written_reqs_tail;
-    unsigned int nr_of_written_reqs;
+    serf_reqlist_t written_reqs;
 
     /* The list of requests that hasn't been written */
-    serf_request_t *unwritten_reqs;
-    serf_request_t *unwritten_reqs_tail;
-    unsigned int nr_of_unwritten_reqs;
+    serf_reqlist_t unwritten_reqs;
 
     /* Requests that are done, but not destroyed yet because they may still
        have data pending in their pools. Will be destroyed at several
        safe points. */
-    serf_request_t *done_reqs;
-    serf_request_t *done_reqs_tail;
+    serf_reqlist_t done_reqs;
 
     serf_connection_setup_t setup;
     void *setup_baton;
@@ -877,17 +879,17 @@ apr_status_t serf__bucket_hpack_create_f
                                         const char *scheme,
                                         serf_bucket_alloc_t *allocator);
 
-/* From connection_request.c */
-void serf__link_requests(serf_request_t **list, serf_request_t **tail,
-                         serf_request_t *request);
+/* From outgoing_request.c */
+void serf__push_request(serf_reqlist_t *list, serf_request_t *request);
+void serf__peek_request(serf_reqlist_t *list, serf_request_t **requestp);
+void serf__take_request(serf_reqlist_t *list, serf_request_t *request);
+void serf__delete_from_reqlist(serf_reqlist_t *list, serf_request_t *request);
 apr_status_t serf__destroy_request(serf_request_t *request);
 apr_status_t serf__cancel_request(serf_request_t *request,
-                                  serf_request_t **list,
+                                  serf_reqlist_t *list,
                                   int notify_request);
-unsigned int serf__req_list_length(serf_request_t *req);
+void serf__req_list_recalc_length(serf_reqlist_t *req);
 apr_status_t serf__setup_request(serf_request_t *request);
-void serf__link_requests(serf_request_t **list, serf_request_t **tail,
-                         serf_request_t *request);
 
 apr_status_t serf__handle_response(serf_request_t *request,
                                    apr_pool_t *pool);

Modified: serf/branches/SERF-195/src/outgoing.c
==============================================================================
--- serf/branches/SERF-195/src/outgoing.c       Wed Aug  6 10:55:54 2025        
(r1927640)
+++ serf/branches/SERF-195/src/outgoing.c       Wed Aug  6 12:02:37 2025        
(r1927641)
@@ -76,7 +76,8 @@ request_pending(serf_request_t **next_re
     {
         /* Skip all requests that have been written completely but we're still
          waiting for a response. */
-        serf_request_t *request = conn->unwritten_reqs;
+        serf_request_t *request;
+        serf__peek_request(&conn->unwritten_reqs, &request);
 
         if (next_req)
             *next_req = request;
@@ -159,8 +160,8 @@ apr_status_t serf__conn_update_pollset(s
         }
     }
 
-    if ((conn->written_reqs || conn->unwritten_reqs) &&
-        conn->state != SERF_CONN_INIT) {
+    if ((conn->written_reqs.head || conn->unwritten_reqs.head)
+        && conn->state != SERF_CONN_INIT) {
         /* If there are any outstanding events, then we want to read. */
         /* ### not true. we only want to read IF we have sent some data */
         desc.reqevents |= APR_POLLIN;
@@ -204,7 +205,7 @@ apr_status_t serf__conn_update_pollset(s
 /* Make sure all response buckets were drained. */
 static void check_buckets_drained(serf_connection_t *conn)
 {
-    serf_request_t *request = conn->written_reqs;
+    serf_request_t *request = conn->written_reqs.head;
 
     for ( ; request ; request = request->next ) {
         if (request->resp_bkt != NULL) {
@@ -220,6 +221,12 @@ static void check_buckets_drained(serf_c
 
 #endif
 
+static serf_reqlist_t reqlist_null = {
+    NULL,                       /* .head */
+    NULL,                       /* .tail */
+    0                           /* .count */
+};
+
 /* Destroys all outstanding write information, to allow cleanup of subpools
    that may still have data in these buckets to continue */
 void serf__connection_pre_cleanup(serf_connection_t *conn)
@@ -230,7 +237,7 @@ void serf__connection_pre_cleanup(serf_c
     serf_pump__done(&conn->pump);
 
     /* Tell all written request that they are free to destroy themselves */
-    rq = conn->written_reqs;
+    rq = conn->written_reqs.head;
     while (rq != NULL) {
         if (rq->writing == SERF_WRITING_STARTED
             || rq->writing == SERF_WRITING_DONE) {
@@ -241,13 +248,13 @@ void serf__connection_pre_cleanup(serf_c
     }
 
     /* Destroy the requests that were queued up to destroy later */
-    while ((rq = conn->done_reqs)) {
-        conn->done_reqs = rq->next;
+    while ((rq = conn->done_reqs.head)) {
+        serf__take_request(&conn->done_reqs, rq);
 
         rq->writing = SERF_WRITING_FINISHED;
         serf__destroy_request(rq);
     }
-    conn->done_reqs = conn->done_reqs_tail = NULL;
+    conn->done_reqs = reqlist_null;
 }
 
 apr_status_t serf_connection__perform_setup(serf_connection_t *conn)
@@ -359,7 +366,7 @@ apr_status_t serf__open_connections(serf
         }
 
         /* Delay opening until we have something to deliver! */
-        if (conn->unwritten_reqs == NULL) {
+        if (conn->unwritten_reqs.head == NULL) {
             continue;
         }
 
@@ -475,7 +482,7 @@ static apr_status_t reset_connection(ser
 {
     serf_context_t *ctx = conn->ctx;
     apr_status_t status;
-    serf_request_t *old_reqs;
+    serf_reqlist_t old_reqs;
 
     serf__log(LOGLVL_DEBUG, LOGCOMP_CONN, __FILE__, conn->config,
               "reset connection 0x%p\n", conn);
@@ -487,8 +494,7 @@ static apr_status_t reset_connection(ser
     /* Clear the unwritten_reqs queue, so the application can requeue cancelled
        requests on it for the new socket. */
     old_reqs = conn->unwritten_reqs;
-    conn->unwritten_reqs = NULL;
-    conn->unwritten_reqs_tail = NULL;
+    conn->unwritten_reqs = reqlist_null;
 
     serf__connection_pre_cleanup(conn);
 
@@ -498,34 +504,34 @@ static apr_status_t reset_connection(ser
     /* First, cancel all written requests for which we haven't received a
        response yet. Inform the application that the request is cancelled,
        so it can requeue them if needed. */
-    while (conn->written_reqs) {
-        serf__cancel_request(conn->written_reqs, &conn->written_reqs,
+    while (conn->written_reqs.head) {
+        serf__cancel_request(conn->written_reqs.head, &conn->written_reqs,
                              requeue_requests);
     }
-    conn->written_reqs_tail = NULL;
+    conn->written_reqs = reqlist_null;
 
     /* Handle all outstanding unwritten requests.
        TODO: what about a partially written request? */
-    while (old_reqs) {
+    while (old_reqs.head) {
         /* If we haven't started to write the connection, bring it over
          * unchanged to our new socket.
          * Do not copy a CONNECT request to the new connection, the ssl tunnel
          * setup code will create a new CONNECT request already.
          */
-        if (requeue_requests && (old_reqs->writing == SERF_WRITING_NONE) &&
-            !old_reqs->ssltunnel) {
+        old_reqs.head->list = &old_reqs;
+        if (requeue_requests && (old_reqs.head->writing == SERF_WRITING_NONE) 
&&
+            !old_reqs.head->ssltunnel)
+        {
 
-            serf_request_t *req = old_reqs;
-            old_reqs = old_reqs->next;
-            req->next = NULL;
-            serf__link_requests(&conn->unwritten_reqs,
-                                &conn->unwritten_reqs_tail,
-                                req);
+            serf_request_t *req = old_reqs.head;
+            serf__take_request(&old_reqs, req);
+            serf__push_request(&conn->unwritten_reqs, req);
         }
-        else {
+        else
+        {
             /* We don't want to requeue the request or this request was 
partially
                written. Inform the application that the request is cancelled. 
*/
-            serf__cancel_request(old_reqs, &old_reqs, requeue_requests);
+            serf__cancel_request(old_reqs.head, &old_reqs, requeue_requests);
         }
     }
 
@@ -577,8 +583,8 @@ static apr_status_t reset_connection(ser
     conn->seen_in_pollset |= APR_POLLHUP;
 
     /* Recalculate the current list length */
-    conn->nr_of_written_reqs = 0;
-    conn->nr_of_unwritten_reqs = serf__req_list_length(conn->unwritten_reqs);
+    conn->written_reqs.count = 0;
+    serf__req_list_recalc_length(&conn->unwritten_reqs);
 
     /* Found the connection. Closed it. All done. */
     return APR_SUCCESS;
@@ -625,21 +631,17 @@ static apr_status_t request_writing_fini
     if (request->writing == SERF_WRITING_DONE) {
         request->writing = SERF_WRITING_FINISHED;
 
-        /* Move the request to the written queue */
-        serf__link_requests(&conn->written_reqs, &conn->written_reqs_tail,
-                            request);
-        conn->nr_of_written_reqs++;
-        conn->unwritten_reqs = conn->unwritten_reqs->next;
-        conn->nr_of_unwritten_reqs--;
-        request->next = NULL;
+        if (conn->unwritten_reqs.head == request) {
+            /* Move the request to the written queue */
+            serf__take_request(&conn->unwritten_reqs, request);
+            serf__push_request(&conn->written_reqs, request);
+        }
 
         /* If our connection has async responses enabled, we're not
-        * going to get a reply back, so kill the request.
-        */
+         * going to get a reply back, so kill the request.
+         */
         if (conn->async_responses) {
-          conn->unwritten_reqs = request->next;
-          conn->nr_of_unwritten_reqs--;
-          serf__destroy_request(request);
+            serf__destroy_request(request);
         }
 
         conn->completed_requests++;
@@ -647,22 +649,15 @@ static apr_status_t request_writing_fini
     /* Destroy (all) requests that are now safe to destroy,
        Typically non or just the finished one */
     {
-        serf_request_t *last = NULL;
-        serf_request_t **rq = &conn->done_reqs;
-        while (*rq) {
-            request = *rq;
-            if ((*rq)->writing == SERF_WRITING_FINISHED) {
-                request = *rq;
-                *rq = request->next;
+        serf_request_t *next;
+        request = conn->done_reqs.head;
+        while (request) {
+            next = request->next;
+            if (request->writing == SERF_WRITING_FINISHED) {
                 serf__destroy_request(request);
             }
-            else {
-                last = *rq;
-                rq = &last->next;
-            }
+            request = next;
         }
-
-        conn->done_reqs_tail = last;
     }
 
     return APR_EOF; /* Done with event bucket. Status is ignored */
@@ -813,10 +808,10 @@ static apr_status_t read_from_connection
         /* Whatever is coming in on the socket corresponds to the first request
          * on our chain.
          */
-        request = conn->written_reqs;
+        serf__peek_request(&conn->written_reqs, &request);
         if (!request) {
             /* Request wasn't completely written yet! */
-            request = conn->unwritten_reqs;
+            serf__peek_request(&conn->unwritten_reqs, &request);
         }
 
         /* We have a different codepath when we can have async responses. */
@@ -943,24 +938,17 @@ static apr_status_t read_from_connection
          $ received.
          * Remove it from our queue and loop to read another response.
          */
-        if (request == conn->written_reqs) {
-            conn->written_reqs = request->next;
-            conn->nr_of_written_reqs--;
+        if (request->list == &conn->written_reqs) {
+            serf__take_request(&conn->written_reqs, request);
         } else {
-            conn->unwritten_reqs = request->next;
-            conn->nr_of_unwritten_reqs--;
+            serf__take_request(&conn->unwritten_reqs, request);
         }
 
         serf__destroy_request(request);
 
-        request = conn->written_reqs;
+        serf__peek_request(&conn->written_reqs, &request);
         if (!request) {
-            /* Received responses for all written requests */
-            conn->written_reqs_tail = NULL;
-            /* Request wasn't completely written yet! */
-            request = conn->unwritten_reqs;
-            if (!request)
-                conn->unwritten_reqs_tail = NULL;
+            serf__peek_request(&conn->unwritten_reqs, &request);
         }
 
         conn->completed_responses++;
@@ -968,7 +956,7 @@ static apr_status_t read_from_connection
         /* We have received a response. If there are no more outstanding
            requests on this connection, we should stop polling for READ events
            for now. */
-        if (!conn->written_reqs && !conn->unwritten_reqs) {
+        if (!conn->written_reqs.head && !conn->unwritten_reqs.head) {
             serf_io__set_pollset_dirty(&conn->io);
         }
 
@@ -1257,13 +1245,9 @@ serf_connection_t *serf_connection_creat
     conn->perform_prioritize_request = NULL;
     conn->protocol_baton = NULL;
 
-    conn->written_reqs = conn->written_reqs_tail = NULL;
-    conn->nr_of_written_reqs = 0;
-
-    conn->unwritten_reqs = conn->unwritten_reqs_tail = NULL;
-    conn->nr_of_unwritten_reqs = 0;
-
-    conn->done_reqs = conn->done_reqs_tail = 0;
+    conn->written_reqs = reqlist_null;
+    conn->unwritten_reqs = reqlist_null;
+    conn->done_reqs = reqlist_null;
 
     /* Create a subpool for our connection. */
     apr_pool_create(&conn->skt_pool, conn->pool);
@@ -1482,11 +1466,11 @@ apr_status_t serf_connection_close(
 
             /* The application asked to close the connection, no need to notify
                it for each cancelled request. */
-            while (conn->written_reqs) {
-                serf__cancel_request(conn->written_reqs, &conn->written_reqs, 
0);
+            while (conn->written_reqs.head) {
+                serf__cancel_request(conn->written_reqs.head, 
&conn->written_reqs, 0);
             }
-            while (conn->unwritten_reqs) {
-                serf__cancel_request(conn->unwritten_reqs, 
&conn->unwritten_reqs, 0);
+            while (conn->unwritten_reqs.head) {
+                serf__cancel_request(conn->unwritten_reqs.head, 
&conn->unwritten_reqs, 0);
             }
             if (conn->skt != NULL) {
                 remove_connection(ctx, conn);
@@ -1624,10 +1608,10 @@ apr_interval_time_t serf_connection_get_
 
 unsigned int serf_connection_queued_requests(serf_connection_t *conn)
 {
-    return conn->nr_of_unwritten_reqs;
+    return conn->unwritten_reqs.count;
 }
 
 unsigned int serf_connection_pending_requests(serf_connection_t *conn)
 {
-    return conn->nr_of_unwritten_reqs + conn->nr_of_written_reqs;
+    return conn->unwritten_reqs.count + conn->written_reqs.count;
 }

Modified: serf/branches/SERF-195/src/outgoing_request.c
==============================================================================
--- serf/branches/SERF-195/src/outgoing_request.c       Wed Aug  6 10:55:54 
2025        (r1927640)
+++ serf/branches/SERF-195/src/outgoing_request.c       Wed Aug  6 12:02:37 
2025        (r1927641)
@@ -18,6 +18,13 @@
  * ====================================================================
  */
 
+#if defined(_DEBUG)
+#include <assert.h>
+#define SERF__REQLIST_assert(x) assert(x)
+#else
+#define SERF__REQLIST_assert(x) ((void)0)
+#endif
+
 #include <stdlib.h>
 
 #include <apr_pools.h>
@@ -91,17 +98,36 @@ static apr_status_t clean_resp(void *dat
     return APR_SUCCESS;
 }
 
-void serf__link_requests(serf_request_t **list, serf_request_t **tail,
-                         serf_request_t *request)
+void serf__push_request(serf_reqlist_t *list, serf_request_t *request)
 {
-    if (*list == NULL) {
-        *list = request;
-        *tail = request;
-    }
-    else {
-        (*tail)->next = request;
-        *tail = request;
+    SERF__REQLIST_assert(request->list == NULL);
+    request->list = list;
+    if (list->head == NULL) {
+        list->head = request;
+        list->tail = request;
+    } else {
+        list->tail->next = request;
+        list->tail = request;
     }
+    ++list->count;
+}
+
+void serf__peek_request(serf_reqlist_t *list, serf_request_t **requestp)
+{
+    serf_request_t *request = list->head;
+    SERF__REQLIST_assert(request == NULL || request->list == list);
+    *requestp = request;
+}
+
+void serf__take_request(serf_reqlist_t *list, serf_request_t *request)
+{
+    SERF__REQLIST_assert(list->head == request && request->list == list);
+    list->head = request->next;
+    if (list->head == NULL)
+        list->tail = NULL;
+    --list->count;
+    request->next = NULL;
+    request->list = NULL;
 }
 
 apr_status_t serf__destroy_request(serf_request_t *request)
@@ -177,6 +203,10 @@ apr_status_t serf__destroy_request(serf_
         request->depends_on = NULL;
     }
 
+    if (request->list != NULL) {
+        serf__delete_from_reqlist(request->list, request);
+    }
+
     if (request->writing >= SERF_WRITING_STARTED
         && request->writing < SERF_WRITING_FINISHED) {
 
@@ -185,8 +215,7 @@ apr_status_t serf__destroy_request(serf_
            Destroying now will destroy memory of buckets that we
            may still need.
         */
-        serf__link_requests(&conn->done_reqs, &conn->done_reqs_tail,
-                            request);
+        serf__push_request(&conn->done_reqs, request);
     }
     else {
 
@@ -203,8 +232,33 @@ apr_status_t serf__destroy_request(serf_
     return APR_SUCCESS;
 }
 
+void serf__delete_from_reqlist(serf_reqlist_t *list, serf_request_t *request)
+{
+    SERF__REQLIST_assert(request->list == list);
+
+    if (list->head == request) {
+        list->head = request->next;
+    } else {
+        serf_request_t *scan = list->head;
+
+        while (scan->next && scan->next != request)
+            scan = scan->next;
+
+        SERF__REQLIST_assert(scan->next == request);
+
+        scan->next = request->next;
+    }
+
+    if (list->head == NULL)
+        list->tail = NULL;
+
+    --list->count;
+    request->next = NULL;
+    request->list = NULL;
+}
+
 apr_status_t serf__cancel_request(serf_request_t *request,
-                                  serf_request_t **list,
+                                  serf_reqlist_t *list,
                                   int notify_request)
 {
     /* If we haven't run setup, then we won't have a handler to call. */
@@ -223,34 +277,23 @@ apr_status_t serf__cancel_request(serf_r
                                               SERF_ERROR_HTTP2_CANCEL);
     }
 
-    if (*list == request) {
-        *list = request->next;
-    }
-    else {
-        serf_request_t *scan = *list;
-
-        while (scan->next && scan->next != request)
-            scan = scan->next;
-
-        if (scan->next) {
-            scan->next = scan->next->next;
-        }
-    }
+    serf__delete_from_reqlist(list, request);
 
     return serf__destroy_request(request);
 }
 
 /* Calculate the length of a linked list of requests. */
-unsigned int serf__req_list_length(serf_request_t *req)
+void serf__req_list_recalc_length(serf_reqlist_t *list)
 {
     unsigned int length = 0;
+    serf_request_t *req = list->head;
 
     while (req) {
         length++;
         req = req->next;
     }
 
-    return length;
+    list->count = length;
 }
 
 apr_status_t serf__setup_request(serf_request_t *request)
@@ -392,7 +435,7 @@ serf__provide_credentials(serf_context_t
         /* request->next will be NULL if this was the last request written */
         authn_req = request->next;
         if (!authn_req)
-            authn_req = conn->unwritten_reqs;
+            authn_req = conn->unwritten_reqs.head;
 
         /* assert: app_request != NULL */
         if (!authn_req)
@@ -446,6 +489,7 @@ create_request(serf_connection_t *conn,
     request->depends_next = NULL;
     request->depends_first = NULL;
     request->dep_priority = SERF_REQUEST_PRIORITY_DEFAULT;
+    request->list = NULL;
 
     return request;
 }
@@ -462,8 +506,7 @@ serf_request_t *serf_connection_request_
                              false /* ssl tunnel */);
 
     /* Link the request to the end of the request chain. */
-    serf__link_requests(&conn->unwritten_reqs, &conn->unwritten_reqs_tail, 
request);
-    conn->nr_of_unwritten_reqs++;
+    serf__push_request(&conn->unwritten_reqs, request);
 
     /* Ensure our pollset becomes writable in context run */
     serf_io__set_pollset_dirty(&conn->io);
@@ -477,8 +520,10 @@ insert_priority_request(serf_request_t *
     serf_request_t *iter, *prev;
     serf_connection_t *conn = request->conn;
 
+    SERF__REQLIST_assert(request->list == NULL);
+
     /* Link the new request after the last written request. */
-    iter = conn->unwritten_reqs;
+    iter = conn->unwritten_reqs.head;
     prev = NULL;
 
     /* TODO: what if a request is partially written? */
@@ -502,14 +547,19 @@ insert_priority_request(serf_request_t *
         }
     }
 
+    request->list = &conn->unwritten_reqs;
     if (prev) {
         request->next = iter;
         prev->next = request;
+        if (conn->unwritten_reqs.tail == prev)
+            conn->unwritten_reqs.tail = request;
     } else {
         request->next = iter;
-        conn->unwritten_reqs = request;
+        conn->unwritten_reqs.head = request;
+        if (conn->unwritten_reqs.tail == NULL)
+            conn->unwritten_reqs.tail = request;
     }
-    conn->nr_of_unwritten_reqs++;
+    ++conn->unwritten_reqs.count;
 
     /* Ensure our pollset becomes writable in context run */
     serf_io__set_pollset_dirty(&conn->io);
@@ -644,14 +694,16 @@ apr_status_t serf_connection__request_re
     }
 
     /* And now make the discard request take the place of the old request */
-    for (pr = &request->conn->written_reqs; *pr; pr = &(*pr)->next) {
+    discard->list = &request->conn->written_reqs;
+    for (pr = &request->conn->written_reqs.head; *pr; pr = &(*pr)->next) {
         if (*pr == request) {
             *pr = discard;
             discard->next = request->next;
             request->next = NULL;
+            request->list = NULL;
 
             if (!discard->next)
-                request->conn->written_reqs_tail = discard;
+                request->conn->written_reqs.tail = discard;
             break;
         }
     }
@@ -689,18 +741,7 @@ apr_status_t serf_connection__request_re
 
 apr_status_t serf_request_cancel(serf_request_t *request)
 {
-    serf_connection_t *conn = request->conn;
-    serf_request_t *tmp = conn->unwritten_reqs;
-
-    /* Find out which queue holds the request */
-    while (tmp != NULL && tmp != request)
-        tmp = tmp->next;
-
-    if (tmp)
-        return serf__cancel_request(request, &conn->unwritten_reqs, 0);
-    else
-        return serf__cancel_request(request, &conn->written_reqs, 0);
-
+    return serf__cancel_request(request, request->list, 0);
 }
 
 void serf_connection_request_prioritize(serf_request_t *request,

Reply via email to