Clocks Are Not Interchangeable — a Class Model of Four Kinds of Clock
generalization arrows point at the shared abstraction; each subclass answers a different question about time
«abstract» Clock
read() : TimeValue
kind : instant | duration
uncertainty : known | hidden
generalization
TimeOfDayClock
CLOCK_REALTIME / ms
synchronized via NTP
can jump back or forward
comparable across nodes
use: timestamps, deadlines
MonotonicClock
CLOCK_MONOTONIC / ns
never jumps, only slewed
rate adjusted up to 0.05%
NOT comparable across nodes
use: timeouts, durations
LogicalClock
counter, no oscillator
Lamport / version vector
measures order only
no notion of seconds
use: causal ordering
UncertaintyClock
TrueTime / ClockBound
returns [earliest, latest]
width = uncertainty bound
narrow bound costs hardware
use: commit wait, snapshots
A reading is not a point in time
The value is really an interval: the machine is 95% sure that now is
between 10.3 and 10.5. Microsecond digits on a ±100 ms clock are noise.
Most APIs hide the interval; TrueTime and ClockBound report it openly.
Which clock for which job
timeout or elapsed time ......... monotonic clock
deadline or calendar time ....... time-of-day clock
ordering across machines ........ logical clock · snapshot stamp ... uncertainty clock
Inheritance is about guarantees, not implementation
A monotonic clock measures how long something took on one machine. Only a logical clock or an uncertainty interval can order events that happen on different machines.