![]() |
Nilorea Library
C utilities for networking, threading, graphics
|
Data Structures | |
| struct | N_CLOCK_SYNC |
| clock synchronization estimator More... | |
Macros | |
| #define | N_CLOCK_SYNC_BURST_INTERVAL 0.5 |
| accelerated interval used until N_CLOCK_SYNC_BURST_SAMPLES real responses have been collected — a fresh estimator converges in a couple of seconds instead of minutes | |
| #define | N_CLOCK_SYNC_BURST_SAMPLES 5 |
| number of REAL samples below which the burst interval applies | |
| #define | N_CLOCK_SYNC_INTERVAL 3.0 |
| default interval between sync requests in seconds | |
| #define | N_CLOCK_SYNC_MAX_RTT 10.0 |
| responses with an RTT above this are rejected outright (retransmit storms / suspend-resume artefacts — not usable timing data) | |
| #define | N_CLOCK_SYNC_SAMPLE_COUNT 11 |
| number of samples for the median filter | |
| #define | N_CLOCK_SYNC_SLEW_SECONDS 1.0 |
| seconds over which n_clock_sync_server_time slews from the previous offset estimate to a new one (smoothstep). | |
Functions | |
| static double | clock_sync_effective_offset (const N_CLOCK_SYNC *cs, double local_now) |
| effective (slewed) offset at local_now — pure function of the stored state so the const getter needs no mutation. | |
| static void | clock_sync_store_sample (N_CLOCK_SYNC *cs, double offset, double rtt, double local_now) |
| store one (offset, rtt) sample and recompute the estimates. | |
| static int | cmp_double (const void *a, const void *b) |
| comparison function for qsort on doubles | |
| static double | median_of (const double *samples, int count) |
| compute the median of an array of doubles | |
| void | n_clock_sync_delete (N_CLOCK_SYNC **cs) |
| free a clock sync estimator | |
| void | n_clock_sync_mark_sent (N_CLOCK_SYNC *cs, double local_now) |
| mark that a sync request was just sent | |
| N_CLOCK_SYNC * | n_clock_sync_new (void) |
| allocate and initialize a new clock sync estimator | |
| int | n_clock_sync_process_response (N_CLOCK_SYNC *cs, double client_send_time, double server_time, double local_now) |
| record a sync response: client_send_time is the local time the request was sent, server_time is the server's timestamp from the response, local_now is the current local time when the response was received. | |
| void | n_clock_sync_seed (N_CLOCK_SYNC *cs, double offset, double rtt) |
| Inject a synthetic (offset, rtt) sample, e.g. | |
| double | n_clock_sync_server_time (const N_CLOCK_SYNC *cs, double local_now) |
| get estimated server time given a local time value. | |
| int | n_clock_sync_should_send (const N_CLOCK_SYNC *cs, double local_now) |
| check if it's time to send a new sync request (returns TRUE/FALSE). | |
| struct N_CLOCK_SYNC |
clock synchronization estimator
Definition at line 105 of file n_clock_sync.h.
Collaboration diagram for N_CLOCK_SYNC:| #define N_CLOCK_SYNC_BURST_INTERVAL 0.5 |
accelerated interval used until N_CLOCK_SYNC_BURST_SAMPLES real responses have been collected — a fresh estimator converges in a couple of seconds instead of minutes
Definition at line 83 of file n_clock_sync.h.
| #define N_CLOCK_SYNC_BURST_SAMPLES 5 |
number of REAL samples below which the burst interval applies
Definition at line 88 of file n_clock_sync.h.
| #define N_CLOCK_SYNC_INTERVAL 3.0 |
default interval between sync requests in seconds
Definition at line 76 of file n_clock_sync.h.
| #define N_CLOCK_SYNC_MAX_RTT 10.0 |
responses with an RTT above this are rejected outright (retransmit storms / suspend-resume artefacts — not usable timing data)
Definition at line 94 of file n_clock_sync.h.
| #define N_CLOCK_SYNC_SAMPLE_COUNT 11 |
number of samples for the median filter
Definition at line 71 of file n_clock_sync.h.
| #define N_CLOCK_SYNC_SLEW_SECONDS 1.0 |
seconds over which n_clock_sync_server_time slews from the previous offset estimate to a new one (smoothstep).
A consumer that anchors motion on this clock sees a bounded rate change instead of a step.
Definition at line 101 of file n_clock_sync.h.
|
static |
effective (slewed) offset at local_now — pure function of the stored state so the const getter needs no mutation.
Blends offset_prev → estimated_offset with a smoothstep over N_CLOCK_SYNC_SLEW_SECONDS from the moment the estimate last changed.
Definition at line 90 of file n_clock_sync.c.
References N_CLOCK_SYNC::estimated_offset, N_CLOCK_SYNC_SLEW_SECONDS, N_CLOCK_SYNC::offset_change_time, and N_CLOCK_SYNC::offset_prev.
Referenced by clock_sync_store_sample(), and n_clock_sync_server_time().
Here is the caller graph for this function:
|
static |
store one (offset, rtt) sample and recompute the estimates.
Offset selection is NTP-style: the sample with the LOWEST rtt wins, because its one-way uncertainty (+/-rtt/2) is the smallest. A plain median is poisoned for minutes when the link is congested at startup (e.g. an MMO client receiving its login chunk burst: every early sample carries seconds of queueing delay, and the median needs a majority of clean samples to recover). estimated_rtt stays a median, it feeds timeout heuristics, where typical beats best.
local_now anchors the slew when the adopted offset changes: n_clock_sync_server_time blends from the previous effective offset instead of stepping.
Definition at line 113 of file n_clock_sync.c.
References clock_sync_effective_offset(), N_CLOCK_SYNC::estimated_offset, N_CLOCK_SYNC::estimated_rtt, median_of(), N_CLOCK_SYNC_SAMPLE_COUNT, N_CLOCK_SYNC::offset_change_time, N_CLOCK_SYNC::offset_prev, N_CLOCK_SYNC::offset_samples, N_CLOCK_SYNC::rtt_samples, N_CLOCK_SYNC::sample_count, and N_CLOCK_SYNC::sample_index.
Referenced by n_clock_sync_process_response(), and n_clock_sync_seed().
Here is the call graph for this function:
Here is the caller graph for this function:
|
static |
comparison function for qsort on doubles
Definition at line 40 of file n_clock_sync.c.
Referenced by median_of().
Here is the caller graph for this function:
|
static |
compute the median of an array of doubles
Definition at line 49 of file n_clock_sync.c.
References cmp_double(), and N_CLOCK_SYNC_SAMPLE_COUNT.
Referenced by clock_sync_store_sample().
Here is the call graph for this function:
Here is the caller graph for this function:| void n_clock_sync_delete | ( | N_CLOCK_SYNC ** | cs | ) |
free a clock sync estimator
Definition at line 79 of file n_clock_sync.c.
References __n_assert, and Free.
Referenced by run_client().
Here is the caller graph for this function:| void n_clock_sync_mark_sent | ( | N_CLOCK_SYNC * | cs, |
| double | local_now | ||
| ) |
mark that a sync request was just sent
Definition at line 199 of file n_clock_sync.c.
References __n_assert, and N_CLOCK_SYNC::last_sync_time.
Referenced by run_client().
Here is the caller graph for this function:| N_CLOCK_SYNC * n_clock_sync_new | ( | void | ) |
allocate and initialize a new clock sync estimator
Definition at line 63 of file n_clock_sync.c.
References __n_assert, N_CLOCK_SYNC::estimated_offset, N_CLOCK_SYNC::estimated_rtt, N_CLOCK_SYNC::last_sync_time, Malloc, N_CLOCK_SYNC_INTERVAL, N_CLOCK_SYNC::sample_count, and N_CLOCK_SYNC::sample_index.
Referenced by run_client().
Here is the caller graph for this function:| int n_clock_sync_process_response | ( | N_CLOCK_SYNC * | cs, |
| double | client_send_time, | ||
| double | server_time, | ||
| double | local_now | ||
| ) |
record a sync response: client_send_time is the local time the request was sent, server_time is the server's timestamp from the response, local_now is the current local time when the response was received.
Updates estimated_offset and estimated_rtt. Returns TRUE on success, FALSE on error.
Definition at line 136 of file n_clock_sync.c.
References __n_assert, clock_sync_store_sample(), N_CLOCK_SYNC::estimated_offset, N_CLOCK_SYNC::estimated_rtt, LOG_DEBUG, LOG_ERR, LOG_WARNING, N_CLOCK_SYNC_MAX_RTT, n_log, N_CLOCK_SYNC::sample_count, N_CLOCK_SYNC::sample_index, and N_CLOCK_SYNC::synthetic.
Referenced by run_client().
Here is the call graph for this function:
Here is the caller graph for this function:| void n_clock_sync_seed | ( | N_CLOCK_SYNC * | cs, |
| double | offset, | ||
| double | rtt | ||
| ) |
Inject a synthetic (offset, rtt) sample, e.g.
a server-supplied clock value at login, so the estimator is usable BEFORE the first request/response round-trip completes. Pass the believed offset (server_time - local_now) and a conservative synthetic rtt. RESETS the estimator to this single sample and adopts the offset immediately (no slew — at login there is nothing to slew from). The FIRST real response flushes the seed wholesale, so a seed with a synthetic rtt lower than the link's real RTT can never pin the estimate (offset selection is best-rtt, NTP-style).
Definition at line 170 of file n_clock_sync.c.
References __n_assert, clock_sync_store_sample(), N_CLOCK_SYNC::estimated_offset, LOG_DEBUG, n_log, N_CLOCK_SYNC::offset_change_time, N_CLOCK_SYNC::offset_prev, N_CLOCK_SYNC::sample_count, N_CLOCK_SYNC::sample_index, and N_CLOCK_SYNC::synthetic.
Here is the call graph for this function:| double n_clock_sync_server_time | ( | const N_CLOCK_SYNC * | cs, |
| double | local_now | ||
| ) |
get estimated server time given a local time value.
When the underlying offset estimate changes, the returned time SLEWS from the previous estimate to the new one over N_CLOCK_SYNC_SLEW_SECONDS (smoothstep) instead of stepping — pure function of the stored state, safe to call at any rate.
Definition at line 184 of file n_clock_sync.c.
References __n_assert, and clock_sync_effective_offset().
Referenced by run_client().
Here is the call graph for this function:
Here is the caller graph for this function:| int n_clock_sync_should_send | ( | const N_CLOCK_SYNC * | cs, |
| double | local_now | ||
| ) |
check if it's time to send a new sync request (returns TRUE/FALSE).
Uses N_CLOCK_SYNC_BURST_INTERVAL until N_CLOCK_SYNC_BURST_SAMPLES real responses have been collected, then N_CLOCK_SYNC_INTERVAL.
Definition at line 189 of file n_clock_sync.c.
References __n_assert, N_CLOCK_SYNC::last_sync_time, N_CLOCK_SYNC_BURST_INTERVAL, N_CLOCK_SYNC_BURST_SAMPLES, N_CLOCK_SYNC_INTERVAL, N_CLOCK_SYNC::sample_count, and N_CLOCK_SYNC::synthetic.
Referenced by run_client().
Here is the caller graph for this function: