mirror of
https://github.com/curl/curl.git
synced 2026-04-14 00:51:42 +08:00
54 lines
2.0 KiB
Markdown
54 lines
2.0 KiB
Markdown
<!--
|
|
Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
|
|
|
SPDX-License-Identifier: curl
|
|
-->
|
|
|
|
# Keeping Time
|
|
|
|
Transfers need the current time to handle timeouts and keep a record of
|
|
events. The current time function is `curlx_now()` and it uses a **monotonic**
|
|
clock on most platforms. This ensures that time only ever increases (the
|
|
timestamps it gives are however not the "real" world clock).
|
|
|
|
## Initial Approach (now historic)
|
|
|
|
The loop processing functions called `curlx_now()` at the beginning and then
|
|
passed a pointer to the `struct curltime now` to functions to save them the
|
|
calls. Passing this pointer down to all functions possibly involved was not
|
|
done as this pollutes the internal APIs.
|
|
|
|
Some functions continued to call `curlx_now()` on their own while others used
|
|
the passed pointer *to a timestamp in the past*. This led to a transfer
|
|
experiencing *jumps* in time, reversing cause and effect. On fast systems,
|
|
this was mostly not noticeable. On slow machines or in CI, this led to rare
|
|
and annoying test failures.
|
|
|
|
(Especially when we added assertions that the reported "timeline" of a
|
|
transfer was in the correct order: *queue -> nameloopup -> connect ->
|
|
appconnect ->...*.)
|
|
|
|
## Revised Approach
|
|
|
|
The strategy of handling transfer's time is now:
|
|
|
|
* Keep a "now" timestamp in the multi handle. Keep a fallback "now" timestamp
|
|
in the easy handle.
|
|
* Always use `Curl_pgrs_now(data)` to get the current time of a transfer.
|
|
* Do not use `curlx_now()` directly for transfer handling (exceptions apply
|
|
for loops).
|
|
|
|
This has the following advantages:
|
|
|
|
* No need to pass a `struct curltime` around or pass a pointer to an outdated
|
|
timestamp to other functions.
|
|
* No need to calculate the exact `now` until it is really used.
|
|
* Passing a `const` pointer is better than struct passing. Updating and
|
|
passing a pointer to the same memory location for all transfers is even
|
|
better.
|
|
|
|
Caveats:
|
|
|
|
* do not store the pointer returned by `Curl_pgrs_now(data)` anywhere that
|
|
outlives the current code invocation.
|