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,