multi: add dirty bitset

Add a bitset `dirty` to the multi handle. The presence of a transfer int
he "dirty" set means: this transfer has something to do ASAP.

"dirty" is set by multiplexing protocols like HTTP/2 and 3 when
encountering response data for another transfer than the current one.
"dirty" is set by protocols that want to be called.

Implementation:

* just an additional `uint_bset` in the multi handle
* `Curl_multi_mark_dirty()` to add a transfer to the dirty set.
* `multi_runsingle()` clears the dirty bit of the transfer at
   start. Without new dirty marks, this empties the set after
   al dirty transfers have been run.
* `multi_timeout()` immediately gives the current time and
   timeout_ms == 0 when dirty transfers are present.
* multi_event: marks all transfers tracked for a socket as dirty.
  Then marks all expired transfers as dirty. Then it runs
  all dirty transfers.

With this mechanism:

* Most uses of `EXPIRE_RUN_NOW` are replaced by `Curl_multi_mark_dirty()`
* `Curl_multi_mark_dirty()` is cheaper than querying if a transfer is
  already dirty or set for timeout. There is no need to check, just do it.
* `data->state.select_bits` is eliminated. We need no longer to
  simulate a poll event to make a transfer run.

Closes #17662
This commit is contained in:
Stefan Eissing 2025-06-18 12:34:43 +02:00 committed by Daniel Stenberg
parent 7aa8d1eea1
commit 779937f840
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
20 changed files with 162 additions and 285 deletions

View file

@ -563,10 +563,9 @@ CURLMcode Curl_multi_ev_assign(struct Curl_multi *multi,
return CURLM_OK;
}
void Curl_multi_ev_expire_xfers(struct Curl_multi *multi,
curl_socket_t s,
const struct curltime *nowp,
bool *run_cpool)
void Curl_multi_ev_dirty_xfers(struct Curl_multi *multi,
curl_socket_t s,
bool *run_cpool)
{
struct mev_sh_entry *entry;
@ -586,9 +585,11 @@ void Curl_multi_ev_expire_xfers(struct Curl_multi *multi,
do {
data = Curl_multi_get_easy(multi, mid);
if(data) {
/* Expire with out current now, so we will get it below when
* asking the splaytree for expired transfers. */
Curl_expire_ex(data, nowp, 0, EXPIRE_RUN_NOW);
Curl_multi_mark_dirty(data);
}
else {
CURL_TRC_M(multi->admin, "socket transfer %u no longer found", mid);
Curl_uint_spbset_remove(&entry->xfers, mid);
}
}
while(Curl_uint_spbset_next(&entry->xfers, mid, &mid));