![]() |
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.
| #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.
Referenced by n_clock_sync_should_send().
| #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.
Referenced by n_clock_sync_should_send().
| #define N_CLOCK_SYNC_INTERVAL 3.0 |
default interval between sync requests in seconds
Definition at line 76 of file n_clock_sync.h.
Referenced by n_clock_sync_new(), and n_clock_sync_should_send().
| #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.
Referenced by n_clock_sync_process_response().
| #define N_CLOCK_SYNC_SAMPLE_COUNT 11 |
number of samples for the median filter
Definition at line 71 of file n_clock_sync.h.
Referenced by clock_sync_store_sample(), and median_of().
| #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.
Referenced by clock_sync_effective_offset().
|
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().
|
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().
|
static |
comparison function for qsort on doubles
Definition at line 40 of file n_clock_sync.c.
Referenced by median_of().
|
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().
| 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().
| 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().
| 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().
| 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().
| 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.
| 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().
| 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().